在没有额外空间的情况下改变阵列

时间:2017-04-18 13:04:32

标签: arrays algorithm time-complexity space-complexity

我在接受采访时得到了以下问题,但无法找到解决方案。

给定一个字符长度 n ,"重要部分" (必须保存此部分中的所有字符)长度 m ,其中 n> = m> = 0 ,如下所示:

enter image description here

没有额外空间,请执行以下过程:
删除所有出现的 A 并复制所有出现的 B ,返回变异数组的子数组。例如,对于上面的数组[C,A,X,B,B,F,Q] n = 7,m = 5,输出将为[C,X,B,B,B,B]。请注意,变异数组长度为6,因为 Q 位于冗余部分, B 重复。

如果不能执行操作,则返回-1。

示例:

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)

寻找代码示例,这可以在O(n)时间复杂度中完成吗?

3 个答案:

答案 0 :(得分:8)

  1. 扫描数组以确定是否可以将变异数组存储在可用空间中 - 计算AB,然后选中N-M >= numB-numA
  2. 从左到右走阵列:向左移动元素A s到目前为止(填充A的位置)
  3. 从右到左移动数组:按numB-B_so_far向右移动元素,插入其他B s

答案 1 :(得分:2)

从输入数组的末尾开始。我们将从后面到前面弄清楚要填写什么。

查看输入中的最后一个重要字符(位置m)。如果是a,请忽略它。否则,添加符号。重复,直到您阅读所有输入。

这会删除a。现在我们将复制b s。

从数组的开头开始。找到您在上述步骤中编写的最后一个值。如果是b,请写两个b。如果它是其他东西,只需写下其中一个。重复。注意:如果你“赶上”,需要写下你需要阅读的地方,你就没有足够的空间而输出-1。否则,将数组的一部分从位置1返回到最后一个读取位置。

示例:

Phase 1: removing A
CAXBBFQ
CAXBBFB
CAXBBBB
CAXBXBB
CAXCXBB

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

阶段1是线性的(我们读取m个符号并且写入不超过m)。

阶段2是线性的(我们读取的符号少于m,并且写入不超过2m)。

m小于n所以一切都是O(m)O(n)

答案 2 :(得分:1)

代码经过一些优化,看起来像这样,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;
}