有条件的全排列

题目:对 {1, 2, 2, 3, 4, 5} 进行无重复的全排列,要求 4 不在第三位,且 3,5 不相连。
思路:用 roll() 方法递归构造所有全排列,将每个构造出的排列做判断之后存入结果集。
java 代码
 
  1. import java.util.ArrayList;  
  2.   
  3. /** 
  4.  * 对 {1, 2, 2, 3, 4, 5} 进行无重复的全排列,要求 4 不在第三位,且 3,5 不相连。 
  5.  * 
  6.  * @author <a href="mailto:yiding.he@chinacreator.com">yidinghe</a> 
  7.  */  
  8. public class AllSort {  
  9.   
  10.     static ArrayList<int[]> results = new ArrayList<int[]>();  
  11.   
  12.     public static void main(String[] args) {  
  13.         int[] ints = {122345};  
  14.         roll(ints, 0);  
  15.         for (int[] result : results) {  
  16.             printArr(result);  
  17.         }  
  18.         System.out.println("结果数量:" + results.size());  
  19.     }  
  20.   
  21.     /** 
  22.      * 递归构造全排列假设要排列的数组已经从小到大排好序。 
  23.      * 
  24.      * @param ints    要排列的数组 
  25.      * @param pointer 进行排列的起始位置 
  26.      */  
  27.     private static void roll(int[] ints, int pointer) {  
  28.         if (ints.length < 2) {  
  29.             return;  
  30.         }  
  31.   
  32.         if (pointer == ints.length - 1) {  
  33.             saveResult(ints);  
  34.             return;  
  35.         }  
  36.   
  37.         int[] cloned;  
  38.         for (int i = pointer; i < ints.length; i++) {  
  39.             cloned = ints.clone();  
  40.             int t = cloned[i];  
  41.             cloned[i] = cloned[pointer];  
  42.             cloned[pointer] = t;  
  43.   
  44.             roll(cloned, pointer + 1);  
  45.         }  
  46.     }  
  47.   
  48.     /** 
  49.      * 判断数组是否与现有结果重复且满足条件,如果是则存入结果。 
  50.      * 
  51.      * @param ints 要保存的数组 
  52.      */  
  53.     private static void saveResult(int[] ints) {  
  54.         boolean exists = false;  
  55.   
  56.         for (int[] result : results) {  
  57.             if (same(result, ints)) {  
  58.                 exists = true;  
  59.                 break;  
  60.             }  
  61.         }  
  62.   
  63.         if (!exists && available(ints)) {  
  64.             results.add(ints);  
  65.         }  
  66.     }  
  67.   
  68.     /** 
  69.      * 比较两个数组是否完全相同 
  70.      * 
  71.      * @param a 一个数组 
  72.      * @param b 另一个数组 
  73.      * 
  74.      * @return 如果数组中每个元素都相同,则返回 true。 
  75.      */  
  76.     private static boolean same(int[] a, int[] b) {  
  77.         boolean same = true;  
  78.         for (int i = 0; i < a.length; i++) {  
  79.             if (a[i] != b[i]) {  
  80.                 same = false;  
  81.                 break;  
  82.             }  
  83.         }  
  84.         return same;  
  85.     }  
  86.   
  87.     /** 
  88.      * 输出数组 
  89.      * 
  90.      * @param ints 要输出的数组 
  91.      */  
  92.     private static void printArr(int[] ints) {  
  93.         for (int n : ints) {  
  94.             System.out.print(n + " ");  
  95.         }  
  96.         System.out.println();  
  97.     }  
  98.   
  99.     /** 
  100.      * 检查数组是否符合要求 
  101.      * 
  102.      * @param ints 要检查的数组 
  103.      * 
  104.      * @return 如果 4 在第三位,或者 3 和 5 相连,则返回 false。 
  105.      */  
  106.     private static boolean available(int[] ints) {  
  107.         return ints[2] != 4 && (Math.abs(indexOf(ints, 3) - indexOf(ints, 5)) > 1);  
  108.     }  
  109.   
  110.     /** 
  111.      * 查找指定数字在数组中的位置 
  112.      * 
  113.      * @param ints 指定数组 
  114.      * @param n    指定数字 
  115.      * 
  116.      * @return 指定数字在数组中的位置。如果找不到,则返回 -1。 
  117.      */  
  118.     private static int indexOf(int[] ints, int n) {  
  119.         for (int i = 0; i < ints.length; i++) {  
  120.             if (ints[i] == n) {  
  121.                 return i;  
  122.             }  
  123.         }  
  124.         return -1;  
  125.     }  
  126. }  

输出结果:
java 代码
 
  1. 1 2 2 3 4 5   
  2. 1 2 2 5 4 3   
  3. 1 2 3 2 4 5   
  4. 1 2 3 2 5 4   
  5. 1 2 3 4 2 5   
  6. 1 2 3 4 5 2   
  7. 1 2 5 4 3 2   
  8. ......  
  9. 5 1 2 2 4 3   
  10. 5 1 2 2 3 4   
  11. 5 1 3 2 4 2   
  12. 5 1 3 2 2 4   
  13. 5 1 3 4 2 2   
  14. 结果数量:198  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值