懂得递归和剪枝,遥远就不远了,一个编程题的感受

来源:互联网 发布:蚁群算法 知乎 编辑:程序博客网 时间:2024/06/04 18:49

        用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求: "4 "不能在第三位, "3 "与 "5 "不能相连。

分析与解答:

 

速度最快,最简单的算法如下,通过那两个约束条件来极大减少搜索空间,只需一个函数就可以满足要求;
只需调用下面这函数就行,设置为
a={1,2,2,3,4,5}; level = 1; prev = -1;
有兴趣的可以研究一下,是不是效果最好的一个

  1.     String[] f(int[] a, int level, int prev) {
  2.         // 只有一个元素,则返回这一个元素即可,这个是原子条件
  3.         if (a.length <= 1) {
  4.             return new String[] { String.valueOf(a[0]) };
  5.         }
  6.         String[] arr = null;
  7.         ArrayList<String> list = new ArrayList<String>();
  8.         int[] b = null;
  9.         for (int i = 0; i < a.length; i++) {
  10.             // 通过两个约束条件来极大的减少搜索空间
  11.             if (level == 3 && a[i] == 4) {// 第三层不能有4
  12.                 continue;
  13.             }
  14.             if (prev == 3 && a[i] == 5 || prev == 5 && a[i] == 3) {// 3和5顺序出现
  15.                 continue;
  16.             }
  17.             // b作为下一个递归条件的开始,其内容是出了a中当前节点之外的其他节点构成的数组
  18.             b = new int[a.length - 1];
  19.             for (int j = 0, k = 0; j < a.length; j++) {
  20.                 if (j != i) {
  21.                     b[k++] = a[j];
  22.                 }
  23.             }
  24.             // 递归调用,对下一层节点进行分析。
  25.             String[] str = f(b, level + 1, a[i]);
  26.             // 组合起来,当前节点和下层节点的返回值组合起来作为整个返回值
  27.             for (int strIndex = 0; strIndex < str.length; strIndex++) {
  28.                 list.add(String.valueOf(a[i]) + str[strIndex]);
  29.             }
  30.         }
  31.         arr = list.toArray(new String[1]);
  32.         return arr;
  33.     }

有兴趣仔细分析之后就知道搜索空间的减少了很多

 

原创粉丝点击