实现元素的全排列

    想到 前几天的一个问题,如何实现元素的全排列 并且按照升序输出。

可以有两种方法:递归和非递归

首先介绍非递归的方法:

思路:

以三个数字为例1,2,3升序的全排列为:

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

显然每个组合  都有一个直接后继,找到一个数没有后继如 3 2 1 则停止。

问题来了 那就是如何找到后继和没有后继的数如何判断该数是否有后继。就是对于一个数,如何找到一个比它大的,且最小的数.

还是1 2 3为例  ,假设 此时的排列为"1 3 2" ,那么32是非递增的,而13是递增的,满足要求,然后根据要求2是比1大的最小的数,此时交换两个数的位置得到2 3 1 ,此时 把交换位置后面的数字颠倒反转即可。得到2 1 3 ,后面的排列都需要这么做,直到碰到3 2 1即可。

代码如下

   1: public class NonRecursivePermutation {

   2:  

   3:     static int[] arr = new int[] { 1, 2, 3, 4, 5, 6 };

   4:     static int count = 1;

   5:  

   6:     // 反转区间

   7:     private static void reverse(int[] arr, int pBegin, int pEnd) {

   8:         while (pBegin < pEnd)

   9:             swap(arr, pBegin++, pEnd--);

  10:     }

  11:  

  12:     private static void swap(int[] arr, int i, int j) {

  13:         int temp;

  14:         temp = arr[i];

  15:         arr[i] = arr[j];

  16:         arr[j] = temp;

  17:     }

  18:  

  19:     private static boolean hasNext() {

  20:         for (int i = arr.length - 1; i > 0; i--) {

  21:             if (arr[i] > arr[i - 1])

  22:                 return true;

  23:         }

  24:         return false;

  25:     }

  26:  

  27:     private static void next() {

  28:         int len = arr.length;

  29:         int replace = 0; // 需替换数

  30:         int firstR = 0; // 从后向前找比替换数大的第一个数

  31:         // 找降序的相邻2数,前一个数即需替换数

  32:         for (int i = len - 1; i > 0; i--) {

  33:             if (arr[i] > arr[i - 1]) {

  34:                 replace = i - 1;

  35:                 break;

  36:             }

  37:         }

  38:         

  39:         //System.out.println("需替换数位置:" + replace);

  40:         

  41:         // 从后向前找比替换数大的第一个数

  42:         // 比如926540的后继应该是946520,而不是956240

  43:         for (int i = len - 1; i > replace; i--) {

  44:             if (arr[i] > arr[replace]) {

  45:                 firstR = i;

  46:                 break; //找到之后直接退出

  47:             }

  48:         }

  49:         

  50:         //System.out.println("替换数位置:" + firstR);

  51:         

  52:         // replace与firstR交换

  53:         swap(arr, replace, firstR);

  54:         // 替换数后的数全部反转

  55:         reverse(arr, replace + 1, len - 1);

  56:  

  57:         count++;

  58:         print();

  59:     }

  60:  

  61:     private static void print() {

  62:         for (int i = 0; i < arr.length; i++)

  63:             System.out.print(arr[i] + " ");

  64:         System.out.println();

  65:     }

  66:  

  67:     /**

  68:      * @param args

  69:      */

  70:     public static void main(String[] args) {

  71:  

  72:         while (hasNext() == true) {

  73:             next();

  74:         }

  75:         System.out.println("数组完全反转后的结果:");

  76:         reverse(arr, 0, arr.length - 1);

  77:         print();

  78:         System.out.println("全排列的数目为:" + count);

  79:  

  80:         /*********************/

  81:         System.out.println("数组是否存在后继:" + hasNext());

  82:         System.out.println("数组一次替换后的结果:");

  83:         next();

  84:     }

  85:  

 }

代码的核心部分是在next和hasNext函数中。

(下篇文章介绍递归的方法)

原文地址:https://www.cnblogs.com/fightingxu/p/2819608.html