本文重点:如果面试题是按照一定要求摆放若干个数字,可以先求出这些数字的所有排列,然后再一一判断每个排列是不是满足题目给定的要求。
基础题:字符串的排列
题目:输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出字符a、b、c所排列出来的所有字符串abc、acb、bac、bca、cab和cba。
思路:将一个字符串看成两个部分:第一部分为它的第一个字符,第二部分是后面的字符。
- 将所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。
- 固定第一个字符,求后面所有字符的排列。
public static void permutation(char[] cs, int index) {
if (index == cs.length) { // 结束交换,进行输出
System.out.println(Arrays.toString(cs));
} else {
for (int loc = index; loc < cs.length; loc++) {
char tmp = cs[loc];
cs[loc] = cs[index];
cs[index] = tmp;
permutation(cs, index + 1);
cs[index] = cs[loc]; // 换回原位置
cs[loc] = tmp;
}
}
}
拓展题目:字符串的组合
题目:如果不是求字符的所有排列,而是求字符的所有组合。例如a、b、c,则它们的组合是a、b、c、ab、ac、ad、bc、abc。
思路:利用Java的位与运算。
知识点: a = 1 << 2; // a =4 (0000 0001 -> 0000 0100)
public static void comb(char[] cs) {
int len = cs.length;
int nbits = 1 << len;
for (int i=0; i<nbits; i++) { // 列举所有的01情况
for (int j=0; j<cs.length; j++) { // 遍历cs,与运算得到是否是1,进行打印
if ((i & (1 << j)) != 0)
System.out.print(cs[j]);
}
System.out.println("");
}
}
变形题一:立方体
题目:输入一个含有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;
}
}
}