6

I was given the following question in an interview, and couldn't find the solution.

Given is an array of chars length n, and "important section" (all chars in this section must be saved) length m where n >= m >= 0 as follows:

enter image description here

Without extra space, perform the following process:
Remove all occurrences of A and duplicate all occurrences of B, return a sub array of the mutated array. For example, for the above array [C,A,X,B,B,F,Q] n=7, m=5 ,output will be [C,X,B,B,B,B]. Note that the mutated array length is 6, since Q was in the redundant section and B was duplicated.

Return -1 if the operation can't be performed.

Examples:

n=2, m=2 , [A,B] => [B,B]  
n=2, m=2 , [B,B] => -1 (since the result [B,B,B,B] is larger then the array)  
n=3, m=2 , [A,B,C] => [B,B]  
n=3, m=3 , [A,B,C] => [B,B,C]  
n=3, m=2 , [Z,B,A] => [Z,B,B] (since A was in the redundant section)

Looking for a code example, Could this be done in O(n) time complexity?

Roni Gadot
  • 437
  • 2
  • 19
  • 30
  • Was the given array "dynamic" as you said "Remove all occurrences of A"? – tourist Apr 18 '17 at 13:18
  • What is the significance of `m`? Why not just ask, given an array of length `n`, remove all `a`s and duplicate all `b`s without using extra space? Is the only concern about `a`s and `b`s in the "redundant section"? – Patrick87 Apr 18 '17 at 13:18
  • m is the length of the chars that must remain, any space behind m can be used for manipulation. – Roni Gadot Apr 18 '17 at 15:48
  • What is an answer for `[B,A,C,B,A,]`? And for `[B,C,A,B,A]`? – user58697 Apr 19 '17 at 06:43

3 Answers3

8
  1. Scan array to determine if is it possible to store mutated array in available space -- count As and B, and check N-M >= numB-numA
  2. Walk array left to right: Shift elements to the left by the number of As so far (filling places of A)
  3. Walk array right to left: Shift elements to the right by numB-B_so_far, inserting additional Bs
pingul
  • 3,351
  • 3
  • 25
  • 43
MBo
  • 77,366
  • 5
  • 53
  • 86
  • What is the time-complexity of the solution? – Roni Gadot Apr 18 '17 at 15:51
  • could you add some code to your response, so I can accept it? – Roni Gadot Apr 18 '17 at 18:17
  • It is O(3n) = O(n). But you could do it with one iteration less. When passing the array the first time delete As and count only the Bs, then decide if it is possible and continue with step 3. – maraca Apr 18 '17 at 19:23
  • @Roni Gadot I believe that everybody could implement such algorithm getting valuable ideas ;-) (Note - this is algorithmic part of SO). Look at optimized version (steps 1 and 2 in a single run) from maraca – MBo Apr 19 '17 at 02:42
  • I agree, that the idea is the most important, otherwise you cannot code. But not only expressing a solution with comprehensible steps is an art-form, the translation of the words to code is too. There are infinite ways to do it, some more elegant than others, and especially for beginners this can be pretty hard. – maraca Apr 19 '17 at 12:44
  • @maraca I was hoping that author would try to code partially, at least 1st step (note - question was from interview). And yes, he/she can learn from your fine code. – MBo Apr 19 '17 at 15:09
2

Start from the end of the input array. We will figure out from the back to the front what to fill in.

Look at the last significant character in the input (position m). If it is a, ignore it. Otherwise, add the symbol. Repeat until you read all the input.

This removes as. Now we will duplicate bs.

Start from the beginning of the array. Find the last value you wrote during the above steps. If it is a b, write two bs. If it is something else, just write one of them. Repeat. NOTE: if you ever "catch up", needing to write where you need to read, you don't have enough room and you output -1. Otherwise, return the part of the array from position 1 to the last read position.

Example:

Phase 1: removing A
CAXBBFQ
CAXBBFB
CAXBBBB
CAXBXBB
CAXCXBB

Phase 2: duplicating B
CAXCXBB
CXXCXBB
CXBBXBB
CXBBBBB
^^^^^^

Phase 1 is linear (we read m symbols and write no more than m).

Phase 2 is linear (we read fewer than m symbols and write no more than 2m).

m is less than n so everything is O(m) and O(n).

Patrick87
  • 27,682
  • 3
  • 38
  • 73
1

The code, with some optimizations, would look something like this, O(n):

// returns length of the relevant part of the mutated array or -1
public static int mutate(char[] a, int m) {
    // delete As and count Bs in the relevant part
    int bCount = 0, position = 0;
    for (int i = 0; i < m; i++) {
        if (a[i] != 'A') {
            if (a[i] == 'B')
                bCount++;
            a[position++] = a[i];
        }
    }
    // check if it is possible
    int n = bCount + position;
    if (n > a.length)
        return -1;
    // duplicate the Bs in the relevant part
    for (int i = position - 1, index = n - 1; i >= 0; i--) {
        if (a[i] != 'B') {
            a[index--] = a[i];
        } else {
            a[index--] = 'B';
            a[index--] = 'B';
        }
    }
    return n;
}
maraca
  • 8,468
  • 3
  • 23
  • 45