1. 用1、2、3、4、5这五个数字,用java写一个main函数,打印出所有不同的排列,如:51234、41235等。
1. public class
2. static int[] bits = new int[] { 1, 2, 3, 4, 5
3.
4. /**
5. * @param args
6. */
7. public static void
8. sort("", bits);
9. }
10.
11. private static void sort(String prefix, int[] a) {
12. if (a.length == 1) {
13. System.out.println(prefix + a[0]);
14. }
15.
16. for (int i = 0; i < a.length; i++) {
17. sort(prefix + a[i], copy(a, i));
18. }
19. }
20.
21. private static int[] copy(int[] a,int
22. int[] b = new int[a.length-1];
23. System.arraycopy(a, 0, b, 0, index);
24. System.arraycopy(a, index+1, b, index, a.length-index-1);
25. return
26. }
27. }
2. 对第一题增加难度,用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连。
基本思路:
2-1. 把问题归结为图结构的遍历问题。图遍历思想:实际上6个数字就是六个结点,把六个结点连接成无向连通图,对于每一个结点求这个图形的遍历路径,所有结点的遍历路径就是最后对这6个数字的排列组合结果集。
2-2. 显然这个结果集还未达到题目的要求。从以下几个方面考虑:
2-2-1. 3,5不能相连:实际要求这个连通图的结点3,5之间不能连通, 可在构造图结构时就满足改条件,然后再遍历图。
2-2-2. 不能有重复: 考虑到有两个2,明显会存在重复结果,可以把结果集放在TreeSet中过滤重复结果
2-2-3. 4不能在第三位: 仍旧在结果集中去除满足此条件的结果。
采用二维数组定义图结构,最后的代码是:
1. import
2. import
3.
4. public class
5.
6. private String[] b = new String[]{"1", "2", "2", "3", "4", "5"};
7. private int
8. private boolean[] visited = new boolean[n];
9. private int[][] a = new int[n][n];
10. private String result = "";
11. private TreeSet set = new
12.
13. public static void
14. new
15. }
16.
17. private void
18.
19. // Initial the map a[][]
20. for (int i = 0; i < n; i++) {
21. for (int j = 0; j < n; j++) {
22. if
23. a[i][j] = 0;
24. } else
25. 1;
26. }
27. }
28. }
29.
30. // 3 and 5 can not be the neighbor.
31. a[3][5] = 0;
32. a[5][3] = 0;
33.
34. // Begin to depth search.
35. for (int i = 0; i < n; i++) {
36. this.depthFirstSearch(i);
37. }
38.
39. // Print result treeset.
40. Iterator it = set.iterator();
41. while
42. String string = (String) it.next();
43. // "4" can not be the third position.
44. if (string.indexOf("4") != 2) {
45. System.out.println(string);
46. }
47. }
48. }
49.
50. private void depthFirstSearch(int
51. visited[startIndex] = true;
52. result = result + b[startIndex];
53. if
54. // Filt the duplicate value.
55. set.add(result);
56. }
57. for(int j = 0; j < n; j++) {
58. if (a[startIndex][j] == 1 && visited[j] == false) {
59. depthFirstSearch(j);
60. } else
61. continue;
62. }
63. }
64.
65. // restore the result value and visited value after listing a node.
66. 0, result.length() -1);
67. false;
68. }
69. }
3. 递归思想。递归要抓住的关键是:(1)递归出口;(2)地推逐步向出口逼近。
3-1. 汉诺塔
这是递归的超经典的例子,几乎每本程序设计书上谈到递归都会介绍。具体情景不再赘述。以我上述的方法观之:
3-1-1. 递归的出口在于disk数为一的时候
3-1-2. 向出口逼近:如果不是一,是n ,则我们先挪动上面n-1块disk,等上面挪完,即递归返回的时候,我们挪动最底下的disk.
仅仅如此,一个貌似十分复杂的问题就解决了,因为挪动那n-1块disk的时候,会继续向上减少,直到disk的数量为一为止。下面给出代码:
1. import
2. public class
3. private static final String DISK_B = "diskB";
4. private static final String DISK_C = "diskC";
5. private static final String DISK_A = "diskA";
6. static
7. static
8. static
9. public static void
10. String input=JOptionPane.showInputDialog("please input the number of the disks you want me move.");
11. int
12. move(num,from,mid,to);
13. }
14. private static void move(int
15. if(num==1){
16. System.out.println("move disk 1 from "+from2+" to "+to2);
17. }
18. else
19. move(num-1,from2,to2,mid2);
20. System.out.println("move disk "+num+" from "+from2+" to "+to2);
21. move(num-1,mid2,from2,to2);
22. }
23. }
24. }
3-2. 这是一个排列的例子,它所做的工作是将输入的一个字符串中的所有元素进行排序并输出,例如:你给出的参数是"abc" 则程序会输出:
abc
acb
bac
bca
cab
cba
分析:
3-2-1. 算法的出口在于:low=high也就是现在给出的排列元素只有一个时;
3-2-2. 算法的逼近过程:先确定排列的第一位元素,也就是循环中i所代表的元素,然后low+1开始减少排列元素,如此下去,直到low=high。(暂未调通)
1. public static void
2. char[] strArray = str.toCharArray();
3. 0, strArray.length - 1);
4. }
5. public static void permute(char[] list, int low, int
6. int
7. if
8. "";
9. for (i = 0; i <= high; i++)
10. cout += list[i];
11. System.out.println(cout);
12. else
13. for
14. char
15. list[low] = list[i];
16. list[i] = temp;
17. 1, high);
18. temp = list[low];
19. list[low] = list[i];
20. list[i] = temp;
21. }
22. }
23. }
3-3. 这是一个组合的例子,与上述的例子相似,只是它所做的工作是,输出所给字符串中制定数目的元素的组合种类。
分析:
3-3-1. 程序出口在于n=1,此时只要输出目标数组的所有元素即可
3-3-2. 逼近过程,当n>1 的时候,我们先取第一个元素放入目标数组中,然后n-1,如此下去,最后出来。
1. import
2. public class
3. /**
4. * @param args
5. */
6. public static void
7. String input = JOptionPane.showInputDialog("please input your String: ");
8. String numString = JOptionPane.showInputDialog("please input the number of your Combination: ");
9. int
10. Combine(input, num);
11. }
12. private static void Combine(String input, int
13. char[] a = input.toCharArray();
14. String b = "";
15. Combine(a, num, b, 0, a.length);
16. }
17. private static void Combine(char[] a, int num, String b, int low, int
18. if (num == 0) {
19. System.out.println(b);
20. } else
21. for (int
22. b += a[i];
23. Combine(a, num - 1, b, i+1, a.length);
24. b=b.substring(0, b.length()-1);
25. }
26. }
27. }
28. }