本文重点:如果面试题是按照一定要求摆放若干个数字,可以先求出这些数字的所有排列,然后再一一判断每个排列是不是满足题目给定的要求。
基础题:字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出字符a、b、c所排列出来的所有字符串abc、acb、bac、bca、cab和cba。
思路:将一个字符串看成两个部分:第一部分为它的第一个字符,第二部分是后面的字符。
- 将所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。
- 固定第一个字符,求后面所有字符的排列。
public void permutation(char[] cs, int index) { if (index == cs.length) { System.out.println(String.valueOf(cs)); return ; } else { for (int loc=index; loc<cs.length; loc++) { char tmp = cs[index]; cs[index] = cs[loc]; cs[loc] = tmp; permutation(cs, index+1); cs[loc] = cs[index]; cs[index] = tmp; } } }
拓展题目:字符串的组合
题目:如果不是求字符的所有排列,而是求字符的所有组合。例如a、b、c,则它们的组合是a、b、c、ab、ac、ad、bc、abc。
思路:利用Java的位与运算。
知识点: a = 1 << 2; // a =4 (0000 0001 -> 0000 0100)
public void comb(char[] cs) { int len = cs.length; // len = 4 int nbits = 1 << len; // nbits = 16. 即0001 0000 // i = 0000 0000 到 0000 1111 for (int i=0; i<nbits; ++i) { int t; for (int j=0; j<len; j++) { // t: 每次左移0位、1位、2位、3位 // t:0000 0001, 0000 0010, 0000 0100, 0000 1000 t = 1 << j; System.out.println(j + "--" + t); if ((t&i) != 0) // 位与运算 System.out.print(cs[j]); } System.out.println("he"); } }
变形题一:立方体
题目:输入一个含有8个数字的数组,判断有没有可能把这8个数字分别放在正方体的8个顶点上(如下图所示)。使得正方体上三组相对的面上的4个顶点的和都相等。
思路:相当于对8个数字进行排列,然后判断有没有某一个的排列符合条件,即a1+a2+a3+a4 = a5+a6+a7+a8,a1+a3+a5+a7=a2+a4+a6+a8,a1+a2+a5+a6=a3+a4+a7+a8。
注意:对数组中的特殊进行排除,比如<=0.
public void cuboid(int[] nums, int index) { if (index == nums.length && nums[0]+nums[1]+nums[2]+nums[3] == nums[4]+nums[5]+nums[6]+nums[7] && nums[0]+nums[2]+nums[4]+nums[6] == nums[1]+nums[3]+nums[5]+nums[7] && nums[0]+nums[1]+nums[4]+nums[5] == nums[2]+nums[3]+nums[6]+nums[7]) { System.out.println(Arrays.toString(nums)); return ; } else { for (int loc=index; loc<nums.length; loc++) { if (nums[loc] <= 0) return ; int tmp = nums[index]; nums[index] = nums[loc]; nums[loc] = tmp; cuboid(nums, index+1); nums[loc] = nums[index]; nums[index] = tmp; } } }
变形题二:八皇后
题目:8皇后的任意两个不能在同一行,同一列,同一条对角线。
思路:定义一个数组,第i个数字表示位于第i行的皇后的列号。首先全排列,只需要判断每一个排列对应的8个皇后是不是在同一条对角线上,也就是数组的任意两个下标i和j,是不是i - j == ColumnIndex[i] - ColumnIndex[j]或者j - i == ColumnIndex[i] - ColumnIndex[j]。
注释:下面代码可以实现n皇后。
public void queen8(int n) { int[] res = new int[n]; for (int i=0; i<n; i++) res[i] = i+1; helpQueen8(res, 0); System.out.println(ser); } public void helpQueen8(int[] nums, int index) { if (index == nums.length) { // 两个皇后不在同一对角线上 for (int i=0; i<nums.length; i++) { for (int j=i+1; j<nums.length; j++) { if (nums[i]-nums[j]==i-j || nums[j]-nums[i]==i-j) return ; } } System.out.println(Arrays.toString(nums)); ser++; return ; } else { for (int loc=index; loc<nums.length; loc++) { int tmp = nums[index]; nums[index] = nums[loc]; nums[loc] = tmp; helpQueen8(nums, index+1); nums[loc] = nums[index]; nums[index] = tmp; } } }