给出由' a'组成的字符串。和' b'只是,允许的操作是删除" abb"的子字符串。如果从字符串出现。我的问题是在应用此操作后,任何时候都不能使字符串为空。我需要一个O(n)算法。
示例, abbabb - >是
aabbbb->是的,因为aabbbb-> abb->空
aaabbb->自aaabbb-> aab 以来没有我现在所能想到的只是一个O(n ^ 2)算法,其中我使用substr()或find()逐步找到子串的位置,然后删除它直到字符串不为空或找不到& #34; ABB"在里面。
答案 0 :(得分:3)
以下是我在评论中建议的一个示例:
for i = 0 to word.length-1
if word[i] == 'b'
if stack.empty() //no corresponding a
return false
if stack.top() == 'a' //first b after an a
stack.push('b')
else //second b after an a
stack.pop() //pop last two letters
stack.pop()
else
stack.push('a')
return stack.empty()
可能存在一些需要检查的边界条件,当然在任何时候pop()失败都需要返回false。似乎正在为我发生的可能输入而努力。
我认为,需要在数学上证明的一点是我在" 之后评论"第二个b的部分。假设堆栈在开始时是空的,如果我没有错过任何看起来正确的点。
答案 1 :(得分:2)
没有必要存储除字符串末尾未使用的b对的数量,因为你从右到左阅读。 (并且它只解读了一次输入,因此O(n)时间为O(1)空间)这非常让人联想到为常规语言找到离散有限自动机。如果你看到两个b,请增加count
。如果你看到一个b,添加一对(更新布尔变量并可能增加计数)。如果你看到a并且没有b对,则失败,否则count--
。如果到达字符串的末尾并且没有额外的b,则字符串有效。
答案 2 :(得分:1)
使用两个计数器以避免使用堆栈。这是c ++实现希望它的工作原理。
bool canBeDone(string s)
{
int aCount = 0;
int bCount = 0;
for(int i=0;i<s.length();++i)
{
if(s[i] == 'a')
{
aCount++;
continue;
}
if(s[i] == 'b' && aCount == 0)
return false;
else
{
bCount += 1;
if(bCount == 2)
{
bCount = 0;
aCount--;
}
}
}
if(!aCount && !bCount)return true;
return false;
}
答案 3 :(得分:0)
在Erlang O(n)
空间和时间中非常简单直接的实现(不幸的是,clwhisk algorithm需要clwhisk在Erlang中需要O(n)
空间,因为{{1 }}):
lists:reverse/1
有algorithm&#39; s {{3}}的C实现作为过滤器:
-module(abb).
-export([check/1, clwhisk/1, test/0]).
check(L) when is_list(L) ->
check(L, []).
check(L, "bba" ++ T) -> check(L, T);
check([H|T], S) -> check(T, [H|S]);
check([], S) -> S =:= [].
clwhisk(L) when is_list(L) ->
clwhisk(lists:reverse(L), 0).
clwhisk([$b|T], C) -> clwhisk(T, C+1);
clwhisk([$a|T], C) -> C >= 2 andalso clwhisk(T, C-2);
clwhisk(L, C) -> L =:= [] andalso C =:= 0.
test() ->
true = abb:check("abbabb"),
true = abb:check("aabbbb"),
false = abb:check("aaabbb"),
true = abb:check("ababbb"),
true = abb:clwhisk("abbabb"),
true = abb:clwhisk("aabbbb"),
false = abb:clwhisk("aaabbb"),
true = abb:clwhisk("ababbb"),
ok.