使用堆栈打印N轮RPS,打印可能结果的所有排列

时间:2016-09-06 07:54:29

标签: algorithm recursion stack

给定n轮,使用堆叠作为主要策略,将所有可能的排列打印到岩纸剪刀上。

我过去常常知道如何做到这一点,但是在没有运动堆栈一段时间之后我就会残缺。

有人可以提供有关如何填充堆栈的有用提示吗?

我知道n输入有3 ^ n个输出。

对于n = 1,预期答案为3.可能的解决方案是:

def rps(n)
  stack = []
  answer = []

  if n > 0
    stack.push([r,p,s])
    n -= 1

  while !stack.isEmpty()
    array = stack.pop();

    forEach elem in array
      // I still can't figure out where to go from here!!

我知道在递归解决方案中,对于n = 1,它会转到r,p,s

对于n = 2,答案附加rr,rp,rs,pr,pp,ps,sr,sp,ss

对于n = 3,它将是rrr,rrp,rrs,rpr等...

2 个答案:

答案 0 :(得分:2)

根据我的理解,我们可以从空堆栈开始,并且对于每个排列弹出堆栈,我们将所有可能性附加到排列,并将其添加回堆栈。

Stack s = new Stack();
s.add("");
ArrayList<String> result;
while(!s.isEmpty()){
    String v = s.pop();
    if(v.length() == n){//All n rounds finished, add to final result
       result.add(v);
       continue;
    }
    //Now, add the result of this round to the current permutation.

    s.push(v + "r");
    s.push(v + "s");
    s.push(v + "p");

}
return result;

答案 1 :(得分:1)

我将这个问题概括为找到从0到N的所有数字排列(在这种情况下N是3)。解决此问题的一种方法是使用递归:

def rec(stack, used):
    if len(stack) == len(L):
        print stack
        i = stack.pop(-1)
        used[i] = 0
        return
    for i in range(len(L)):
        if used[i] == 0:
            stack.append(i)
            used[i] = 1
            rec(stack,used)
    if len(stack):
        i = stack.pop(-1)
        used [i] = 0
    else:
        return
N = 3
rec([],[0]*N,N) 

我们所做的是将第一个未使用的项目附加到列表中并再次调用该函数(回溯)。当我们的列表是完整打印列表。这给出了所有可能的排列:

[0, 1, 2]
[0, 2, 1]
[1, 0, 2]
[1, 2, 0]
[2, 0, 1]
[2, 1, 0]

虽然这种方法正在使用堆栈,但我怀疑它实际上是问题的意图。

问题的主要思想是实现回溯方法以在迭代方法中查找列表的所有排列。这就是堆栈进入的地方。

我们可以通过使用堆栈简单地模仿递归函数:

stack = [(0,1)]
used = [1,0,0]
N = 3

def iterative():
    while 1:
        if len(stack) == N:
            print [x[0] for x in stack]
            i,x = stack.pop(-1)
            used[i] = 0
            continue
        top = stack.pop(-1)
        index = top[1]
        for i in range(index,N):
            if used[i] == 0:
                stack.append( (top[0],i+1) )
                stack.append( (i,0) )
                used[i] = 1
                break
        else:
            used[top[0]] = 0
            if len(stack)==0:
                if top[0]+1 < N:
                    stack.append((top[0]+1,0))
                    used[top[0]+1] = 1
                else:
                    break

唯一的区别是递归函数中有一些局部变量,一旦执行它们就会记住它们。我们可以将这些局部变量放在堆栈中。在这种情况下,除了我们在列表中放入的实际项目之外,我们还记得从什么值继续检查(这是递归函数中for循环的变量)。这就是:

#[stack] [used]
[(0, 1)] [1, 0, 0]
[(0, 2), (1, 0)] [1, 1, 0]
[(0, 2), (1, 3), (2, 0)] [1, 1, 1]
A new permutation:  [0, 1, 2]
[(0, 2), (1, 3)] [1, 1, 0]
[(0, 2)] [1, 0, 0]
[(0, 3), (2, 0)] [1, 0, 1]
[(0, 3), (2, 2), (1, 0)] [1, 1, 1]
A new permutation:  [0, 2, 1]
[(0, 3), (2, 2)] [1, 0, 1]
[(0, 3)] [1, 0, 0]
[(1, 0)] [0, 1, 0]
[(1, 1), (0, 0)] [1, 1, 0]
[(1, 1), (0, 3), (2, 0)] [1, 1, 1]
A new permutation:  [1, 0, 2]
[(1, 1), (0, 3)] [1, 1, 0]
[(1, 1)] [0, 1, 0]
[(1, 3), (2, 0)] [0, 1, 1]
[(1, 3), (2, 1), (0, 0)] [1, 1, 1]
A new permutation:  [1, 2, 0]
[(1, 3), (2, 1)] [0, 1, 1]
[(1, 3)] [0, 1, 0]
[(2, 0)] [0, 0, 1]
[(2, 1), (0, 0)] [1, 0, 1]
[(2, 1), (0, 2), (1, 0)] [1, 1, 1]
A new permutation:  [2, 0, 1]
[(2, 1), (0, 2)] [1, 0, 1]
[(2, 1)] [0, 0, 1]
[(2, 2), (1, 0)] [0, 1, 1]
[(2, 2), (1, 1), (0, 0)] [1, 1, 1]
A new permutation:  [2, 1, 0]
[(2, 2), (1, 1)] [0, 1, 1]
[(2, 2)] [0, 0, 1]
Finished