使用O(1)空间进行行程编码

时间:2012-06-07 06:41:11

标签: algorithm run-length-encoding

我们可以在适当的位置进行游程编码(假设输入数组非常大) 我们可以为AAAABBBBCCCCDDDD等案例做 A4B4C4D4

但是对于像ABCDEFG这样的情况怎么办呢? 其中输出为A1B1C1D1E1F1G1

6 个答案:

答案 0 :(得分:1)

C ++解决方案O(n)时间O(1)空间

string runLengthEncode(string str)
{
    int len = str.length();
    int j=0,k=0,cnt=0;
    for(int i=0;i<len;i++)
    {
        j=i;
        cnt=1;
        while(i<len-1 && str[i]==str[i+1])
        {
            i++;
            cnt++;
        }
        str[k++]=str[j];
        string temp =to_string(cnt);
        for(auto m:temp)
            str[k++] = m;
    }
    str.resize(k);
    return str;
}

答案 1 :(得分:1)

我的第一个想法是从最后开始编码,所以我们将使用空闲空间(如果有的话),之后我们可以将编码数组移到开头。这种方法的一个问题是它不适用于AAAAB,因为没有空闲空间(A4B1不需要它),我们将尝试在第一次迭代时编写AAAAB1。

以下是更正后的解决方案: (让我们假设序列是AAABBC)

  1. 使用两个或更多元素编码所有组,并保持其余组不变(这不会增加数组的长度) - &gt; A3_B2C
  2. 在第一步之后将一切正确移除空白空间 - &gt; _A3B2C
  3. 从头开始编码数组(当然重用已编码的组) - &gt; A3B2C1
  4. 每一步都是O(n),据我所知,只需要不断的额外内存。

    限制:

    1. 不支持数字,但无论如何都会产生像Petar Petrov所提到的解码问题。
    2. 我们需要某种&#34;空&#34;字符,但这可以通过添加零来解决:A03而不是A3 _

答案 2 :(得分:0)

null用于指示哪些项为空,并且将被忽略以进行编码。你也不能编码数字(AAA2222 =&gt; A324 =&gt; 324倍'A',但它是A3; 24)。您的问题会提出更多问题。

这是C#中的“解决方案”

public static void Encode(string[] input)
{
    var writeIndex = 0;

    var i = 0;
    while (i < input.Length)
    {
        var symbol = input[i];
        if (symbol == null)
        {
            break;
        }

        var nextIndex = i + 1;

        var offset = 0;
        var count = CountSymbol(input, symbol, nextIndex) + 1;
        if (count == 1)
        {
            ShiftRight(input, nextIndex);
            offset++;
        }

        input[writeIndex++] = symbol;
        input[writeIndex++] = count.ToString();

        i += count + offset;
    }

    Array.Clear(input, writeIndex, input.Length - writeIndex);
}

private static void ShiftRight(string[] input, int nextIndex)
{
    var count = CountSymbol(input, null, nextIndex, (a, b) => a != b);
    Array.Copy(input, nextIndex, input, nextIndex + 1, count);
}

private static int CountSymbol(string[] input, string symbol, int nextIndex)
{
    return CountSymbol(input, symbol, nextIndex, (a, b) => a == b);
}

private static int CountSymbol(string[] input, string symbol, int nextIndex, Func<string, string, bool> cmp)
{
    var count = 0;

    var i = nextIndex;
    while (i < input.Length && cmp(input[i], symbol))
    {
        count++;
        i++;
    }

    return count;
}

答案 3 :(得分:0)

第一种解决方案不处理单个字符。例如 - '嗨!'不管用。我使用了完全不同的方法,使用'insert()'函数添加到位。这将照顾一切,无论总的“相同”字符是&gt; 10或> 100或= 1。

#include<iostream>
#include<algorithm>
using namespace std;

int main(){
    string name = "Hello Buddy!!";
    int start = 0;
    char distinct = name[0];
    for(int i=1;i<name.length()+1;){
        if(distinct!=name[i]){
            string s = to_string(i-start);
            name.insert(start+1,s);
            name.erase(name.begin() + start + 1 + s.length(),name.begin() + s.length() + i);
            i=start+s.length()+1;
            start=i;
            distinct=name[start];
            continue;
        }
        i++;
    }
    cout<<name;
}

如果您发现任何错误,建议我。

答案 4 :(得分:0)

O(n),就地RLE,我想不出更好。它不会放置一个数字,如果chars occurence只是1.如果角色出现11次,也会放置a9a2。

void RLE(char *str) {
int len = strlen(str);
int count = 1, j = 0;
for (int i = 0; i < len; i++){
    if (str[i] == str[i + 1])
        count++;
    else {
        int times = count / 9;
        int rem = count % 9;
        for (int k = 0; k < times; k++) {
            str[j++] = str[i];
            _itoa(9, &str[j++], 10);
            count = count - 9;
        }
        if (count > 1) {
            str[j++] = str[i];
            _itoa(rem, &str[j++], 10);
            count = 1;
        }
        else 
            str[j++] = str[i];
    }
}
cout << str;

}

I / P =&gt; aaabcdeeeefghijklaaaaa

O / P =&gt; a3bcde4fghijkla5

答案 5 :(得分:0)

 Inplace solution using c++ ( assumes length of encoding string is not more than actual string length):

    #include <bits/stdc++.h>
    #include<stdlib.h>
    using namespace std;

    void replacePattern(char *str)
    {
        int len = strlen(str);
        if (len == 0)
        return;

        int i = 1, j = 1;
        int count;

        // for each character
        while (str[j])
        {
            count = 1;
            while (str[j] == str[j-1])
            {
                j = j + 1;
                count++;
            }

            while(count > 0) {
                int rem = count%10;
                str[i++] = to_string(rem)[0];
                count = count/10;
            }
            // copy character at current position j
            // to position i and increment i and j
            if (str[j])
                str[i++] = str[j++];
        }

        // add a null character to terminate string
        if(str[len-1] != str[len-2]) {
            str[i] = '1';
            i++;
        }
        str[i] = '\0';
    }

    // Driver code
    int main()
    {
        char str[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabccccc";
        replacePattern(str);
        cout << str;
        return 0;
    }