【问题标题】:Permutation of array数组的排列
【发布时间】:2011-02-24 14:33:34
【问题描述】:

例如我有这个数组:

int a[] = new int[]{3,4,6,2,1};

我需要所有排列的列表,这样如果一个是这样的,{3,2,1,4,6},其他的一定不一样。我知道如果数组的长度是 n 那么有 n! 个可能的组合。这个算法怎么写?

更新:谢谢,但我需要一个伪代码算法,例如:

for(int i=0;i<a.length;i++){
    // code here
}

只是算法。是的,API 函数很好,但对我帮助不大。

【问题讨论】:

  • 没有 2^n 个可能的组合。有n! 排列。另外,我不明白这个问题。您是否只是想排除单个排列 {3,2,1,4,6}
  • 是的,对不起!没有所有排列都应该是唯一的
  • 可以添加其他语言标签吗?由于这是一种算法,因此最好有多种语言的多种实现。

标签: java c++ algorithm


【解决方案1】:

以下是如何在 10 行代码中打印所有排列:

public class Permute{
    static void permute(java.util.List<Integer> arr, int k){
        for(int i = k; i < arr.size(); i++){
            java.util.Collections.swap(arr, i, k);
            permute(arr, k+1);
            java.util.Collections.swap(arr, k, i);
        }
        if (k == arr.size() -1){
            System.out.println(java.util.Arrays.toString(arr.toArray()));
        }
    }
    public static void main(String[] args){
        Permute.permute(java.util.Arrays.asList(3,4,6,2,1), 0);
    }
}

您获取数组的第一个元素 (k=0) 并将其与数组的任何元素 (i) 交换。然后你递归地对从第二个元素开始的数组应用排列。这样你就得到了从第 i 个元素开始的所有排列。棘手的部分是,在递归调用之后,您必须将第 i 个元素与第一个元素交换回来,否则您可能会在第一个位置获得重复值。通过交换它,我们恢复了元素的顺序(基本上你做回溯)。

重复值情况下的迭代器和扩展

以前算法的缺点是它是递归的,不能很好地与迭代器配合使用。另一个问题是,如果您在输入中允许重复元素,那么它将无法按原样工作。

例如,给定输入 [3,3,4,4] 所有可能的排列(没有重复)是

[3, 3, 4, 4]
[3, 4, 3, 4]
[3, 4, 4, 3]
[4, 3, 3, 4]
[4, 3, 4, 3]
[4, 4, 3, 3]

(如果你只是简单地从上面应用permute函数,你会得到四次[3,3,4,4],这不是你在这种情况下自然想要看到的;并且这种排列的数量是4!/(2!*2!)=6)

可以修改上述算法来处理这种情况,但看起来不太好。幸运的是,有一个更好的算法(我发现它here)可以处理重复值并且不是递归的。

首先请注意,任何对象数组的排列都可以通过以任何顺序枚举它们来简化为整数的排列。

要获得一个整数数组的排列,你需要从一个按升序排列的数组开始。你的“目标”是让它下降。为了生成下一个排列,您尝试从底部开始查找序列未能降序的第一个索引,并提高该索引中的值,同时在这种情况下将尾部其余部分的顺序从降序切换到升序。

这里是算法的核心:

//ind is an array of integers
for(int tail = ind.length - 1;tail > 0;tail--){
    if (ind[tail - 1] < ind[tail]){//still increasing

        //find last element which does not exceed ind[tail-1]
        int s = ind.length - 1;
        while(ind[tail-1] >= ind[s])
            s--;

        swap(ind, tail-1, s);

        //reverse order of elements in the tail
        for(int i = tail, j = ind.length - 1; i < j; i++, j--){
            swap(ind, i, j);
        }
        break;
    }
}

这里是迭代器的完整代码。构造函数接受一个对象数组,并使用HashMap 将它们映射到一个整数数组中。

import java.lang.reflect.Array;
import java.util.*;
class Permutations<E> implements  Iterator<E[]>{

    private E[] arr;
    private int[] ind;
    private boolean has_next;

    public E[] output;//next() returns this array, make it public

    Permutations(E[] arr){
        this.arr = arr.clone();
        ind = new int[arr.length];
        //convert an array of any elements into array of integers - first occurrence is used to enumerate
        Map<E, Integer> hm = new HashMap<E, Integer>();
        for(int i = 0; i < arr.length; i++){
            Integer n = hm.get(arr[i]);
            if (n == null){
                hm.put(arr[i], i);
                n = i;
            }
            ind[i] = n.intValue();
        }
        Arrays.sort(ind);//start with ascending sequence of integers


        //output = new E[arr.length]; <-- cannot do in Java with generics, so use reflection
        output = (E[]) Array.newInstance(arr.getClass().getComponentType(), arr.length);
        has_next = true;
    }

    public boolean hasNext() {
        return has_next;
    }

    /**
     * Computes next permutations. Same array instance is returned every time!
     * @return
     */
    public E[] next() {
        if (!has_next)
            throw new NoSuchElementException();

        for(int i = 0; i < ind.length; i++){
            output[i] = arr[ind[i]];
        }


        //get next permutation
        has_next = false;
        for(int tail = ind.length - 1;tail > 0;tail--){
            if (ind[tail - 1] < ind[tail]){//still increasing

                //find last element which does not exceed ind[tail-1]
                int s = ind.length - 1;
                while(ind[tail-1] >= ind[s])
                    s--;

                swap(ind, tail-1, s);

                //reverse order of elements in the tail
                for(int i = tail, j = ind.length - 1; i < j; i++, j--){
                    swap(ind, i, j);
                }
                has_next = true;
                break;
            }

        }
        return output;
    }

    private void swap(int[] arr, int i, int j){
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public void remove() {

    }
}

使用/测试:

    TCMath.Permutations<Integer> perm = new TCMath.Permutations<Integer>(new Integer[]{3,3,4,4,4,5,5});
    int count = 0;
    while(perm.hasNext()){
        System.out.println(Arrays.toString(perm.next()));
        count++;
    }
    System.out.println("total: " + count);

打印出所有7!/(2!*3!*2!)=210 排列。

【讨论】:

  • 很好的答案。你能解释一下为什么它是 4!/(2!2!)=6 而不是 4!/(2!)=12
  • 首先,我知道答案是 6(来自我的 [3,3,4,4] 示例)。要导出公式,请将 [3,3,4,4] 视为两个蓝色球和两个红色球。问题是有多少种定位球的方法(相同颜色的球是相同的)。如果你以某种方式定位你的球,那么交换蓝色球(2!这样做的方法)或两个红球(2!这样做的方法)不会改变任何事情。现在,我们有4个!放置 4 个球的方式,但排列蓝球(2!方式)或红球(2!方式)不会改变球的位置。所以你得到 4!/(2!*2!) 作为最终答案
  • 第一个算法的时间复杂度是O(n*n!),是吗?
  • 这是我尝试过的最快的置换算法。干得好
  • 我很少喜欢对 SO 进行冗长的解释,但这是一个很棒的例外。感谢您的解释!
【解决方案2】:

如果您使用 C++,则可以使用 &lt;algorithm&gt; 头文件中的 std::next_permutation

int a[] = {3,4,6,2,1};
int size = sizeof(a)/sizeof(a[0]);
std::sort(a, a+size);
do {
  // print a's elements
} while(std::next_permutation(a, a+size));

【讨论】:

    【解决方案3】:

    这里是Java中Permutation的一个实现:

    Permutation - Java

    你应该检查一下!

    编辑:粘贴下面的代码以防止链接死亡:

    // Permute.java -- A class generating all permutations
    
    import java.util.Iterator;
    import java.util.NoSuchElementException;
    import java.lang.reflect.Array;
    
    public class Permute implements Iterator {
    
       private final int size;
       private final Object [] elements;  // copy of original 0 .. size-1
       private final Object ar;           // array for output,  0 .. size-1
       private final int [] permutation;  // perm of nums 1..size, perm[0]=0
    
       private boolean next = true;
    
       // int[], double[] array won't work :-(
       public Permute (Object [] e) {
          size = e.length;
          elements = new Object [size];    // not suitable for primitives
          System.arraycopy (e, 0, elements, 0, size);
          ar = Array.newInstance (e.getClass().getComponentType(), size);
          System.arraycopy (e, 0, ar, 0, size);
          permutation = new int [size+1];
          for (int i=0; i<size+1; i++) {
             permutation [i]=i;
          }
       }
    
       private void formNextPermutation () {
          for (int i=0; i<size; i++) {
             // i+1 because perm[0] always = 0
             // perm[]-1 because the numbers 1..size are being permuted
             Array.set (ar, i, elements[permutation[i+1]-1]);
          }
       }
    
       public boolean hasNext() {
          return next;
       }
    
       public void remove() throws UnsupportedOperationException {
          throw new UnsupportedOperationException();
       }
    
       private void swap (final int i, final int j) {
          final int x = permutation[i];
          permutation[i] = permutation [j];
          permutation[j] = x;
       }
    
       // does not throw NoSuchElement; it wraps around!
       public Object next() throws NoSuchElementException {
    
          formNextPermutation ();  // copy original elements
    
          int i = size-1;
          while (permutation[i]>permutation[i+1]) i--;
    
          if (i==0) {
             next = false;
             for (int j=0; j<size+1; j++) {
                permutation [j]=j;
             }
             return ar;
          }
    
          int j = size;
    
          while (permutation[i]>permutation[j]) j--;
          swap (i,j);
          int r = size;
          int s = i+1;
          while (r>s) { swap(r,s); r--; s++; }
    
          return ar;
       }
    
       public String toString () {
          final int n = Array.getLength(ar);
          final StringBuffer sb = new StringBuffer ("[");
          for (int j=0; j<n; j++) {
             sb.append (Array.get(ar,j).toString());
             if (j<n-1) sb.append (",");
          }
          sb.append("]");
          return new String (sb);
       }
    
       public static void main (String [] args) {
          for (Iterator i = new Permute(args); i.hasNext(); ) {
             final String [] a = (String []) i.next();
             System.out.println (i);
          }
       }
    }
    

    【讨论】:

    • +1 请将相关代码添加到您的帖子中,以防链接失效
    • 也感谢您消除了行号。 :P
    • 链接失效了。 :)
    • @BlueRaja-DannyPflughoeft 不错,链接失效了
    【解决方案4】:

    这是一个包含在迭代器中的列表的 2 排列

    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    
    /* all permutations of two objects 
     * 
     * for ABC: AB AC BA BC CA CB
     * 
     * */
    public class ListPermutation<T> implements Iterator {
    
        int index = 0;
        int current = 0;
        List<T> list;
    
        public ListPermutation(List<T> e) {
            list = e;
        }
    
        public boolean hasNext() {
            return !(index == list.size() - 1 && current == list.size() - 1);
        }
    
        public List<T> next() {
            if(current == index) {
                current++;
            }
            if (current == list.size()) {
                current = 0;
                index++;
            }
            List<T> output = new LinkedList<T>();
            output.add(list.get(index));
            output.add(list.get(current));
            current++;
            return output;
        }
    
        public void remove() {
        }
    
    }
    

    【讨论】:

      【解决方案5】:

      对于给定的数组大小n,有n! 的总排列。这是使用 DFS 用 Ja​​va 编写的代码。

      public List<List<Integer>> permute(int[] nums) {
          List<List<Integer>> results = new ArrayList<List<Integer>>();
          if (nums == null || nums.length == 0) {
              return results;
          }
          List<Integer> result = new ArrayList<>();
          dfs(nums, results, result);
          return results;
      }
      
      public void dfs(int[] nums, List<List<Integer>> results, List<Integer> result) {
          if (nums.length == result.size()) {
              List<Integer> temp = new ArrayList<>(result);
              results.add(temp);
          }        
          for (int i=0; i<nums.length; i++) {
              if (!result.contains(nums[i])) {
                  result.add(nums[i]);
                  dfs(nums, results, result);
                  result.remove(result.size() - 1);
              }
          }
      }
      

      对于输入数组[3,2,1,4,6],总共有5个! = 120 种可能的排列:

      [[3,4,6,2,1],[3,4,6,1,2],[3,4,2,6,1],[3,4,2,1,6],[3,4,1,6,2],[3,4,1,2,6],[3,6,4,2,1],[3,6,4,1,2],[3,6,2,4,1],[3,6,2,1,4],[3,6,1,4,2],[3,6,1,2,4],[3,2,4,6,1],[3,2,4,1,6],[3,2,6,4,1],[3,2,6,1,4],[3,2,1,4,6],[3,2,1,6,4],[3,1,4,6,2],[3,1,4,2,6],[3,1,6,4,2],[3,1,6,2,4],[3,1,2,4,6],[3,1,2,6,4],[4,3,6,2,1],[4,3,6,1,2],[4,3,2,6,1],[4,3,2,1,6],[4,3,1,6,2],[4,3,1,2,6],[4,6,3,2,1],[4,6,3,1,2],[4,6,2,3,1],[4,6,2,1,3],[4,6,1,3,2],[4,6,1,2,3],[4,2,3,6,1],[4,2,3,1,6],[4,2,6,3,1],[4,2,6,1,3],[4,2,1,3,6],[4,2,1,6,3],[4,1,3,6,2],[4,1,3,2,6],[4,1,6,3,2],[4,1,6,2,3],[4,1,2,3,6],[4,1,2,6,3],[6,3,4,2,1],[6,3,4,1,2],[6,3,2,4,1],[6,3,2,1,4],[6,3,1,4,2],[6,3,1,2,4],[6,4,3,2,1],[6,4,3,1,2],[6,4,2,3,1],[6,4,2,1,3],[6,4,1,3,2],[6,4,1,2,3],[6,2,3,4,1],[6,2,3,1,4],[6,2,4,3,1],[6,2,4,1,3],[6,2,1,3,4],[6,2,1,4,3],[6,1,3,4,2],[6,1,3,2,4],[6,1,4,3,2],[6,1,4,2,3],[6,1,2,3,4],[6,1,2,4,3],[2,3,4,6,1],[2,3,4,1,6],[2,3,6,4,1],[2,3,6,1,4],[2,3,1,4,6],[2,3,1,6,4],[2,4,3,6,1],[2,4,3,1,6],[2,4,6,3,1],[2,4,6,1,3],[2,4,1,3,6],[2,4,1,6,3],[2,6,3,4,1],[2,6,3,1,4],[2,6,4,3,1],[2,6,4,1,3],[2,6,1,3,4],[2,6,1,4,3],[2,1,3,4,6],[2,1,3,6,4],[2,1,4,3,6],[2,1,4,6,3],[2,1,6,3,4],[2,1,6,4,3],[1,3,4,6,2],[1,3,4,2,6],[1,3,6,4,2],[1,3,6,2,4],[1,3,2,4,6],[1,3,2,6,4],[1,4,3,6,2],[1,4,3,2,6],[1,4,6,3,2],[1,4,6,2,3],[1,4,2,3,6],[1,4,2,6,3],[1,6,3,4,2],[1,6,3,2,4],[1,6,4,3,2],[1,6,4,2,3],[1,6,2,3,4],[1,6,2,4,3],[1,2,3,4,6],[1,2,3,6,4],[1,2,4,3,6],[1,2,4,6,3],[1,2,6,3,4],[1,2,6,4,3]]
      

      希望这会有所帮助。

      【讨论】:

        【解决方案6】:

        原始数组示例:

        public static void permute(int[] intArray, int start) {
            for(int i = start; i < intArray.length; i++){
                int temp = intArray[start];
                intArray[start] = intArray[i];
                intArray[i] = temp;
                permute(intArray, start + 1);
                intArray[i] = intArray[start];
                intArray[start] = temp;
            }
            if (start == intArray.length - 1) {
                System.out.println(java.util.Arrays.toString(intArray));
            }
        }
        
        public static void main(String[] args){
            int intArr[] = {1, 2, 3};
            permute(intArr, 0);
        }
        

        【讨论】:

          【解决方案7】:

          根据维基https://en.wikipedia.org/wiki/Heap%27s_algorithm

          堆算法生成 n 个对象的所有可能排列。它由 B. R. Heap 在 1963 年首次提出。该算法最小化移动:它通过交换一对元素从前一个排列生成每个排列;其他 n-2 个元素不受干扰。 在 1977 年对排列生成算法的回顾中,Robert Sedgewick 得出结论,它是当时由计算机生成排列的最有效算法。

          所以如果我们想以递归的方式来做,Sudo 代码如下。

          procedure generate(n : integer, A : array of any):
              if n = 1 then
                    output(A)
              else
                  for i := 0; i < n - 1; 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
                  generate(n - 1, A)
              end if
          

          java代码:

          public static void printAllPermutations(
                  int n, int[] elements, char delimiter) {
              if (n == 1) {
                  printArray(elements, delimiter);
              } else {
                  for (int i = 0; i < n - 1; i++) {
                      printAllPermutations(n - 1, elements, delimiter);
                      if (n % 2 == 0) {
                          swap(elements, i, n - 1);
                      } else {
                          swap(elements, 0, n - 1);
                      }
                  }
                  printAllPermutations(n - 1, elements, delimiter);
              }
          }
          
          private static void printArray(int[] input, char delimiter) {
              int i = 0;
              for (; i < input.length; i++) {
                  System.out.print(input[i]);
              }
              System.out.print(delimiter);
          }
          
          private static void swap(int[] input, int a, int b) {
              int tmp = input[a];
              input[a] = input[b];
              input[b] = tmp;
          }
          
          public static void main(String[] args) {
              int[] input = new int[]{0,1,2,3};
              printAllPermutations(input.length, input, ',');
          }
          

          【讨论】:

            【解决方案8】:

            3 项递归解决方案的可视化表示: http://www.docdroid.net/ea0s/generatepermutations.pdf.html

            细分:

            1. 对于包含两项的数组,有两种排列方式:
              • 原始数组和
              • 交换了两个元素
            2. 对于三项数组,有六种排列:
              • 底部两个元素的排列,然后
              • 交换第一个和第二个项目,以及底部两个元素的排列
              • 交换第 1 项和第 3 项,以及底部两个元素的排列。
              • 基本上,每个项目都会在第一个插槽中获得机会

            【讨论】:

              【解决方案9】:

              一个简单的java实现,参考c++std::next_permutation

              public static void main(String[] args){
                  int[] list = {1,2,3,4,5};
                  List<List<Integer>> output = new Main().permute(list);
                  for(List result: output){
                      System.out.println(result);
                  }
              
              }
              
              public List<List<Integer>> permute(int[] nums) {
                  List<List<Integer>> list = new ArrayList<List<Integer>>();
                  int size = factorial(nums.length);
              
                  // add the original one to the list
                  List<Integer> seq = new ArrayList<Integer>();
                  for(int a:nums){
                      seq.add(a);
                  }
                  list.add(seq);
              
                  // generate the next and next permutation and add them to list
                  for(int i = 0;i < size - 1;i++){
                      seq = new ArrayList<Integer>();
                      nextPermutation(nums);
                      for(int a:nums){
                          seq.add(a);
                      }
                      list.add(seq);
                  }
                  return list;
              }
              
              
              int factorial(int n){
                  return (n==1)?1:n*factorial(n-1);
              }
              
              void nextPermutation(int[] nums){
                  int i = nums.length -1; // start from the end
              
                  while(i > 0 && nums[i-1] >= nums[i]){
                      i--;
                  }
              
                  if(i==0){
                      reverse(nums,0,nums.length -1 );
                  }else{
              
                      // found the first one not in order 
                      int j = i;
              
                      // found just bigger one
                      while(j < nums.length && nums[j] > nums[i-1]){
                          j++;
                      }
                      //swap(nums[i-1],nums[j-1]);
                      int tmp = nums[i-1];
                      nums[i-1] = nums[j-1];
                      nums[j-1] = tmp;
                      reverse(nums,i,nums.length-1);  
                  }
              }
              
              // reverse the sequence
              void reverse(int[] arr,int start, int end){
                  int tmp;
                  for(int i = 0; i <= (end - start)/2; i++ ){
                      tmp = arr[start + i];
                      arr[start + i] = arr[end - i];
                      arr[end - i ] = tmp;
                  }
              }
              

              【讨论】:

                【解决方案10】:

                这样做...

                import java.util.ArrayList;
                import java.util.Arrays;
                
                public class rohit {
                
                    public static void main(String[] args) {
                        ArrayList<Integer> a=new ArrayList<Integer>();
                        ArrayList<Integer> b=new ArrayList<Integer>();
                        b.add(1);
                        b.add(2);
                        b.add(3);
                        permu(a,b);
                    }
                
                    public static void permu(ArrayList<Integer> prefix,ArrayList<Integer> value) {
                        if(value.size()==0) {
                            System.out.println(prefix);
                        } else {
                            for(int i=0;i<value.size();i++) {
                                ArrayList<Integer> a=new ArrayList<Integer>();
                                a.addAll(prefix);
                                a.add(value.get(i));
                
                                ArrayList<Integer> b=new ArrayList<Integer>();
                
                                b.addAll(value.subList(0, i));
                                b.addAll(value.subList(i+1, value.size()));
                
                                permu(a,b);
                            }
                        }
                    }
                
                }
                

                【讨论】:

                  【解决方案11】:

                  通过递归(动态编程)实现,在 Java 中使用测试用例 (TestNG)。


                  代码

                  PrintPermutation.java

                  import java.util.Arrays;
                  
                  /**
                   * Print permutation of n elements.
                   * 
                   * @author eric
                   * @date Oct 13, 2018 12:28:10 PM
                   */
                  public class PrintPermutation {
                      /**
                       * Print permutation of array elements.
                       * 
                       * @param arr
                       * @return count of permutation,
                       */
                      public static int permutation(int arr[]) {
                          return permutation(arr, 0);
                      }
                  
                      /**
                       * Print permutation of part of array elements.
                       * 
                       * @param arr
                       * @param n
                       *            start index in array,
                       * @return count of permutation,
                       */
                      private static int permutation(int arr[], int n) {
                          int counter = 0;
                          for (int i = n; i < arr.length; i++) {
                              swapArrEle(arr, i, n);
                              counter += permutation(arr, n + 1);
                              swapArrEle(arr, n, i);
                          }
                          if (n == arr.length - 1) {
                              counter++;
                              System.out.println(Arrays.toString(arr));
                          }
                  
                          return counter;
                      }
                  
                      /**
                       * swap 2 elements in array,
                       * 
                       * @param arr
                       * @param i
                       * @param k
                       */
                      private static void swapArrEle(int arr[], int i, int k) {
                          int tmp = arr[i];
                          arr[i] = arr[k];
                          arr[k] = tmp;
                      }
                  }
                  

                  PrintPermutationTest.java (测试用例来自TestNG)

                  import org.testng.Assert;
                  import org.testng.annotations.Test;
                  
                  /**
                   * PrintPermutation test.
                   * 
                   * @author eric
                   * @date Oct 14, 2018 3:02:23 AM
                   */
                  public class PrintPermutationTest {
                      @Test
                      public void test() {
                          int arr[] = new int[] { 0, 1, 2, 3 };
                          Assert.assertEquals(PrintPermutation.permutation(arr), 24);
                  
                          int arrSingle[] = new int[] { 0 };
                          Assert.assertEquals(PrintPermutation.permutation(arrSingle), 1);
                  
                          int arrEmpty[] = new int[] {};
                          Assert.assertEquals(PrintPermutation.permutation(arrEmpty), 0);
                      }
                  }
                  

                  【讨论】:

                    【解决方案12】:

                    这是一个使用数组和 Java 8+ 的例子

                    import java.util.Arrays;
                    import java.util.stream.IntStream;
                    
                    public class HelloWorld {
                    
                        public static void main(String[] args) {
                            int[] arr = {1, 2, 3, 5};
                            permutation(arr, new int[]{});
                        }
                    
                        static void permutation(int[] arr, int[] prefix) {
                            if (arr.length == 0) {
                                System.out.println(Arrays.toString(prefix));
                            }
                            for (int i = 0; i < arr.length; i++) {
                                int i2 = i;
                                int[] pre = IntStream.concat(Arrays.stream(prefix), IntStream.of(arr[i])).toArray();
                                int[] post = IntStream.range(0, arr.length).filter(i1 -> i1 != i2).map(v -> arr[v]).toArray();
                                permutation(post, pre);
                            }
                        }
                    }
                    

                    【讨论】:

                      【解决方案13】:

                      我们最好将它们称为组合,而不是排列

                      不考虑编码语言,我们可以使用简单的方法, To append the array elements to the already existing list of combinations 因此,使用dynamic programming 方法。

                      此代码也关注那些无邻接的组合。

                      #include <iostream>
                      #include <vector>
                      using namespace std;
                      
                      template <class myIterator, class T>
                      myIterator findDigit(myIterator first, myIterator last, T val)
                      {
                          while(first != last) {
                              if(*first == val) { break; }
                              first++;
                          }
                          return first;
                      }
                      
                      void printCombinations(vector<vector<int>> combinations)
                      {
                          cout << "printing all " << combinations.size() << " combinations" << endl;
                          for(int i=0; i<combinations.size(); i++) {
                              cout << "[";
                              for(int j=0; j<combinations[i].size(); j++) {
                                  cout << " " << combinations[i][j] << " ";
                              }
                              cout << "] , ";
                          }
                          return;
                      }
                      
                      int main()
                      {
                          vector<int> a = {1,2,3,4,5};
                          vector<vector<int>> comb;
                          vector<int> t;
                          int len=a.size();
                      
                          for(int i=0; i<len; i++) {
                              t.push_back(a.at(i));
                              comb.push_back(t);
                              t.clear();
                          }
                      
                          for(int l=1; l<len; l++) {
                              for(int j=0; j<comb.size(); j++) {
                                  if(comb[j].size()==l) {
                                      int t = comb[j].back();
                                      if(t != a.back()) {
                                          vector<int>::iterator it = findDigit(a.begin(), a.end(), t);
                                          for(std::vector<int>::iterator k=it+1; k!=a.end();k++) {
                                              vector<int> t (comb[j].begin(), comb[j].end());
                                              t.push_back(*k);
                                              comb.push_back(t);
                                              t.clear();
                                          }
                                      }
                                  }
                              }
                          }
                      
                          printCombinations(comb);
                          return 0;
                      }
                      

                      虽然复杂度有点高,但肯定比递归的方法要低,尤其是当数组很大的时候。

                      上述数组(或向量,如果你愿意的话)的输出是:

                      printing all 31 combinations
                      [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ], [ 1  2 ], [ 1  3 ], [ 1  4 ], [ 1  5 ], [ 2  3 ], [ 2  4 ], [ 2  5 ], [ 3  4 ], [ 3  5 ], [ 4  5 ], [ 1 
                       2  3 ], [ 1  2  4 ], [ 1  2  5 ], [ 1  3  4 ], [ 1  3  5 ], [ 1  4  5 ], [ 2  3  4 ], [ 2  3  5 ], [ 2  4  5 ], [ 3  4  5 ], [ 1  2  3  4 
                      ], [ 1  2  3  5 ], [ 1  2  4  5 ], [ 1  3  4  5 ], [ 2  3  4  5 ], [ 1  2  3  4  5 ],
                      

                      代码也可以用于字符和字符串,只需在需要的地方替换数据类型。

                      例如。

                      vector<char> a = {'d','g','y','u','t'};
                      

                      给予

                      printing all 31 combinations
                      [ d ] , [ g ] , [ y ] , [ u ] , [ t ] , [ d  g ] , [ d  y ] , [ d  u ] , [ d  t ] , [ g  y ] , [ g  u ] , [ g  t ] , [ y  u ] , [ y  t ] , 
                      [ u  t ] , [ d  g  y ] , [ d  g  u ] , [ d  g  t ] , [ d  y  u ] , [ d  y  t ] , [ d  u  t ] , [ g  y  u ] , [ g  y  t ] , [ g  u  t ] , [ 
                      y  u  t ] , [ d  g  y  u ] , [ d  g  y  t ] , [ d  g  u  t ] , [ d  y  u  t ] , [ g  y  u  t ] , [ d  g  y  u  t ] ,
                      

                      vector<string> a = {"asdf","myfl", "itshot", "holy"};
                      

                      给予

                      printing all 15 combinations
                      [ asdf ] , [ myfl ] , [ itshot ] , [ holy ] , [ asdf  myfl ] , [ asdf  itshot ] , [ asdf  holy ] , [ myfl  itshot ] , [ myfl  holy ] , [ itshot  holy ] , [ asdf  myfl  itshot ] , [ asdf  myfl  holy ] , [ asdf  itshot  holy ] , [ myfl  itshot  holy ] , [ asdf  myfl  itshot  holy ] ,
                      

                      【讨论】:

                      • 他们从N 中询问N排列(可以重新排列多少种独特的方式?)(通常,这会忽略相等性检查,假设所有值是“独特的”)。您确实提供了N 中的1..=N组合,保持顺序。两个完全不同的词,两个完全不同的问题。
                      猜你喜欢
                      • 2010-10-17
                      • 1970-01-01
                      • 2021-01-26
                      • 2012-05-30
                      • 2013-08-26
                      • 1970-01-01
                      相关资源
                      最近更新 更多