我正在为周一的面试做准备,我发现这个问题需要解决,称为“字符串缩减”。问题是这样表述的:
给定一个由 a、b 和 c 组成的字符串,我们可以执行以下操作:取任意两个相邻的不同字符并将其替换为第三个字符。例如,如果“a”和“c”相邻,则可以将它们替换为“b”。通过重复应用此操作可以产生的最小字符串是多少?
例如,cab -> cc 或 cab -> bb,产生长度为 2 的字符串。对于这个,一个最佳解决方案是:bcab -> aab -> ac -> b。不能再进行任何操作,结果字符串的长度为 1。如果字符串 = CCCCC,则不能执行任何操作,因此答案为 5。
我在stackoverflow上看到了很多问题和答案,但我想验证我自己的算法。这是我的伪代码算法。在我的代码中
- S是我要减少的字符串
- S[i] 是索引 i 处的字符
- P 是一个堆栈:
redux 是减少字符的函数。
function reduction(S[1..n]){ P = create_empty_stack(); for i = 1 to n do car = S[i]; while (notEmpty(P)) do head = peek(p); if( head == car) break; else { popped = pop(P); car = redux (car, popped); } done push(car) done return size(P)}
我的算法的最坏情况是 O(n),因为堆栈 P 上的所有操作都在 O(1) 上。我在上面的例子中尝试了这个算法,我得到了预期的答案。让我用这个例子“ abacbcaa ”执行我的算法:
i = 1 :
car = S[i] = a, P = {∅}
P is empty, P = P U {car} -> P = {a}
i = 2 :
car = S[i] = b, P = {a}
P is not empty :
head = a
head != car ->
popped = Pop(P) = a
car = reduction (car, popped) = reduction (a,b) = c
P = {∅}
push(car, P) -> P = {c}
i = 3 :
car = S[i] = a, P = {c}
P is not empty :
head = c
head != car ->
popped = Pop(P) = c
car = reduction (car, popped) = reduction (a,c) = b
P = {∅}
push(car, P) -> P = {b}
...
i = 5 : (interesting case)
car = S[i] = c, P = {c}
P is not empty :
head = c
head == car -> break
push(car, P) -> P = {c, c}
i = 6 :
car = S[i] = b, P = {c, c}
P is not empty :
head = c
head != car ->
popped = Pop(P) = c
car = reduction (car, popped) = reduction (b,c) = a
P = {c}
P is not empty : // (note in this case car = a)
head = c
head != car ->
popped = Pop(P) = c
car = reduction (car, popped) = reduction (a,c) = b
P = {∅}
push(car, P) -> P = {b}
... and it continues until n
我已经在这样的各种示例上运行了这个算法,它似乎有效。我用 Java 编写了一个测试该算法的代码,当我将代码提交给系统时,我得到了错误的答案。我已经在gisthub上发布了 java 代码, 所以你可以看到它。
有人能告诉我我的算法有什么问题吗?