在没有for循环的情况下查找Array的排列

时间:2015-05-28 14:37:36

标签: arrays algorithm permutation

我在LinkedIn小组here

上看到了这个采访问题

总结一下,如果我有一个数组

[1,2,3,4,5]

并输入

3

我需要输出

[1,2,3], [3,2,1], [2,3,1], [2,1,3], [1,3,2], [3,1,2], [2,3,4], [4,3,2],...

没有特别的顺序。

我一直在考虑这个问题。我提出了各种不同的解决方法,但所有方法都使用for循环。

我认为很明显,为了消除循环,它必须是递归的。

我认为我接近于以递归方式对数组进行分区并加入元素,但是由于非常沮丧,我最终需要另一个for循环。

我开始认为这是不可能的(它不可能,否则为什么面试问题?)。

任何想法或链接?可能的输出量应为5PN,其中N为输入。

6 个答案:

答案 0 :(得分:1)

以下递归算法将尝试打印{1,..,n}的每个子集。这些子集通过以下双射一对一地具有0到2 ^ n-1之间的数字:对于0到2 ^ n-1之间的整数x,如果x的第一位设置为0,则关联包含1的集合一,如果x的第二位设置为1,则为2,..

void print_all_subsets (int n, int m, int x) {
    if (x==pow(2,n)) {
        return;
    }
    else if (x has m bits set to one) {
        print the set corresponding to x;
    }
    print_all_subsets(n,m,x+1);
}

你需要用n = 5(在你的情况下),m = 3(在你的情况下)和x = 0来调用它。

然后你需要实现两个函数“打印对应于x的集合”和“x有m位设置为1”而不用for循环...但这很容易使用再次递归。

但是,我认为这更具挑战性 - 完全消除for循环没有意义,只有以聪明的方式使用它们才有意义。

答案 1 :(得分:1)

你的第一个想法是正确的。每个循环都可以用递归替换。在某些语言(例如Scheme)中,循环实际上是通过递归实现的。所以从任何解决方案开始,继续将循环转换为递归。最终你会完成。

这是一个Python的工作解决方案。

def subsets_of_size (array, size, start=0, prepend=None):
    if prepend is None:
        prepend = [] # Standard Python precaution with modifiable defaults.
    if 0 == size:
        return [[] + prepend] # Array with one thing.  The + forces a copy.
    elif len(array) < start + size:
        return [] # Array with no things.
    else:
        answer = subsets_of_size(array, size, start=start + 1, prepend=prepend)
        prepend.append(array[start])
        answer = answer + subsets_of_size(array, size-1, start=start + 1, prepend=prepend)
        prepend.pop()
        return answer

print subsets_of_size([1,2,3,4,5], 3)

答案 2 :(得分:0)

你可以在这里使用递归,每次你调用一个内层时,你给它在数组中的位置,当它返回它时返回一个增加的位置。您已经为此使用了一个while循环。

伪代码:

int[] input = [1,2,3,4,5];
int level = 3;

int PrintArrayPermutation(int level, int location, string base)
{
    if (level == 0)
    {
        print base + input[location];
        return location + 1;
    }

    while (location <= input.Length)
    {
        location = 
            PrintArrayPermutation(level - 1, location, base + input[location]);
    }
}

这是我的想法的基本概要。

答案 3 :(得分:0)

我认为解决方案不是使用for-loop,而是有一种使用for循环的最佳方法。

所以,有Heap的算法。以下是wiki http://en.wikipedia.org/wiki/Heap%27s_algorithm

procedure generate(n : integer, A : array of any):
    if n = 1 then
          output(A)
    else
        for i := 0; i < n; i += 1 do
            generate(n - 1, A)
            if n is even then
                swap(A[i], A[n - 1])
            else
                swap(A[0], A[n-1])
            end if
        end for
    end if

答案 4 :(得分:0)

define listPermutations:
    input: int p_l , int[] prevP , int atElement , int[] val , int nextElement
    output: list

    if nextElement > length(val) OR atElement == p_l OR contains(prevP , val[nextElement]
        return EMPTY

    list result

    int[] tmp = copy(prevP)
    tmp[atElement] = val[nextElement]
    add(result , tmp)

    //create the next permutation stub with the last sign different to this sign 
    //(node with the same parent)
    addAll(result , listPermutations(p_l , tmp , atElement , val , nextElement + 1))

    //create the next permutation stub with an additional sign
    //(child node of the current permutation
    addAll(result , listPermutations(p_l , tmp , atElement + 1 , val , 0))

    return result

//this will return the permutations for your example input:
listPermutations(3 , new int[3] , 0 , int[]{1 , 2 , 3 , 4 , 5} , 0)

基本思想:给定数量元素的所有排列形成树,其中节点是空排列,节点的所有子节点都有一个额外元素。现在,算法所要做的就是逐级遍历这个树,直到该级别等于所需的排列长度并列出该级别上的所有节点

答案 5 :(得分:0)

以下是JavaScript中的两个递归函数。第一个是组合choose函数,我们应用第二个函数,置换每个结果(permutator改编自SO用户,分隔符,在此回答:Permutations in JavaScript?

function c(n,list){
  var result = [];
  function _c(p,r){
    if (p > list.length)
      return
    if (r.length == n){
      result = result.concat(permutator(r));
    } else {
      var next = list[p],
          _r = r.slice();
      _r.push(next)
      _c(p+1,_r);
      _c(p+1,r);
    }
  }
  _c(0,[])
  return result;
}

function permutator(inputArr) {
  var results = [];

  function permute(arr, memo) {
    var cur, memo = memo || [];

    function _permute (i,arr,l){
      if (i == l)
        return
      cur = arr.splice(i,1);
      if (arr.length === 0){
        results.push(memo.concat(cur));
      }
      permute(arr.slice(), memo.concat(cur));
      arr.splice(i, 0, cur[0]);
      _permute(i + 1,arr,l)
    }
    _permute(0,arr,arr.length);
    return results;
  }

  return permute(inputArr);
}

输出:

console.log(c(3,[1,2,3,4,5]))

[[1,2,3],[1,3,2],[2,1,3]...[4,5,3],[5,3,4],[5,4,3]]
相关问题