求解字符串约简算法

时间:2012-05-26 13:00:07

标签: java algorithm pseudocode

我正准备自己接受星期一的采访,我发现这个问题需要解决“String Reduction”。问题是这样说的:

  

给定由a,b和c组成的字符串,我们可以执行以下操作   操作:取两个相邻的不同字符并替换它   与第三个字符。例如,如果'a'和'c'相邻,   他们可以用'b'代替。什么是最小的字符串可以   重复应用此操作的结果?

     

例如,cab - > cc或cab - > bb,产生一串长度   对于这个,一个最佳解决方案是:bcab - > aab - > ac - >湾不能再应用任何操作,结果字符串的长度为1。   如果字符串是= CCCCC,则不能执行任何操作,因此   答案是5。

我在stackoverflow上看到了很多questions and answers,但我想验证自己的算法。这是我的伪代码算法。在我的代码中

  1. S是我要减少的字符串
  2. S [i]是索引i的字符
  3. P是一个堆栈:
  4. 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)}
    
  5. 我算法的最坏情况是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代码,因此您可以看到它。

    有人能告诉我算法有什么问题吗?

2 个答案:

答案 0 :(得分:5)

我将尝试解释nhahtdh的含义。您的算法失败的原因有很多。但最基本的一点是,在每个时间点,只有观察到的第一个角色有机会被推到堆栈p。不应该这样,因为你可以从任何位置开始减少。

让我给你一个字符串abcc。如果我在

断点
car = S[i];

算法运行:

p = {∅}, s = _abcc //underscore is the position
p = {a}, s = a_bcc  
p = {c}, s = ab_cc  

此时您仍然处于缩减ccc

但还有另一种减少:abcc -> aac ->ab ->c

此外,返回堆栈P的大小是错误的。 cc无法减少,但是 算法将返回1。您还应该计算跳过的次数。

答案 1 :(得分:0)

你也可以使用强力...和递归来解决这个问题

for all n-1 pairs(2 char) replace it with 3rd char if possible and apply reduce on this new string of length n-1
    for all n-2 pairs replace it with 3rd char and apply reduce on new string
         for all n-3 pairs....and so on

长度为n-1的新字符串将具有n-2对,类似地,长度为n-2的新字符串将具有n-3对。

在应用此方法时,请保持存储最小值

if (new_min < min)
    min = new_min

实施:http://justprogrammng.blogspot.com/2012/06/interviewstreet-challenge-string.html