我在接受采访时得到了以下问题,但无法找到解决方案。
给定一个字符长度 n ,"重要部分" (必须保存此部分中的所有字符)长度 m ,其中 n> = m> = 0 ,如下所示:
没有额外空间,请执行以下过程:
删除所有出现的 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)时间复杂度中完成吗?
答案 0 :(得分:8)
A
和B
,然后选中N-M >= numB-numA
A
s到目前为止(填充A的位置)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;
}