3

Can we do the run-length encoding in place(assuming the input array is very large) We can do for the cases such as AAAABBBBCCCCDDDD A4B4C4D4

But how to do it for the case such as ABCDEFG? where the output would be A1B1C1D1E1F1G1

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Luv
  • 5,381
  • 9
  • 48
  • 61
  • 2
    In place? This would require the input array to be large enough, at most 2·n where n is the amount of input characters. – Gumbo Jun 07 '12 at 06:50
  • Yes, let us assume that we have – Luv Jun 07 '12 at 07:54
  • But then the space needed still depends on `n`! You cannot do this with an arbitrarily large string and a dictionary with a well-defined size. The string may always be larger than the space allotted. But maybe you don't really mean `O(1)` space? – Emil Vikström Jun 07 '12 at 09:12
  • If the output is larger than the input array then, no, you can't do the encoding in place. And you can't know if the output will be larger than the input without first doing a full scan of the input string. – Jim Mischel Aug 15 '16 at 15:58

6 Answers6

2

My first thought was to start encoding from the end, so we will use the free space (if any), after that we can shift the encoded array to the start. A problem with this approach is that it will not work for AAAAB, because there is no free space (it's not needed for A4B1) and we will try to write AAAAB1 on the first iteration.

Below is corrected solution: (let's assume the sequence is AAABBC)

  1. encode all groups with two or more elements and leave the rest unchanged (this will not increase length of the array) -> A3_B2C
  2. shift everything right eliminating empty spaces after first step -> _A3B2C
  3. encode the array from the start (reusing the already encoded groups of course) -> A3B2C1

Every step is O(n) and as far as I can see only constant additional memory is needed.

Limitations:

  1. Digits are not supported, but that anyway would create problems with decoding as Petar Petrov mentioned.
  2. We need some kind of "empty" character, but this can be worked around by adding zeros: A03 instead of A3_
maxim1000
  • 6,297
  • 1
  • 23
  • 19
1

C++ solution O(n) time O(1) space

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;
}
learner
  • 123
  • 2
  • 11
  • Unless I missed something, the code will not work correctly for ABCDEFG. After the first iteration it will overwrite B with 1 and will lose B forever. – maxim1000 Aug 14 '16 at 19:43
0

null is used to indicate which items are empty and will be ignored for encoding. Also you can't encode digits (AAA2222 => A324 => 324 times 'A', but it's A3;24). Your question opens more questions.

Here's a "solution" in 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;
}
Petar Petrov
  • 2,729
  • 2
  • 22
  • 17
0

The 1st solution does not take care of single characters. For example - 'Hi!' will not work. I've used totally different approach, used 'insert()' functions to add inplace. This take care of everything, whether the total 'same' character is > 10 or >100 or = 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;
}

Suggest me if you find anything incorrect.

0

O(n), in-place RLE, I couldn't think better than this. It will not place a number, if chars occurence is just 1. Will also place a9a2, if the character comes 11 times.

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 => aaabcdeeeefghijklaaaaa

O/P => a3bcde4fghijkla5

Hemant Yadav
  • 307
  • 1
  • 4
  • 19
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;
    }
Prateek Sharma
  • 109
  • 2
  • 9