字符串的排列与组合
2016-05-28 17:18
471 查看
字符串全排列
求字符串的排列可以把字符串看成两部分:第一部分为它的第一个字符,第二部分是后面的所有字符。求字符串的全排列的时候,可以用两步完成:首先求所有可能出现在第一个位置的字符,即把第一个字符与后面的所有字符交换。第二步固定第一个字符,求后面所有字符的排列。从中可以看出是典型的递归思路。
/** * 字符串的全排列 */ public class Permutation { @Test public void testCase() { permutation("abcc"); } /** * 求字符串的全排列 * * @param str */ public void permutation(String str) { permutation(str.toCharArray(), 0); } /** * 求begin位置开始字符数组的排列 * * @param strArr 字符数组 * @param begin begin位置 */ private void permutation(char[] strArr, int begin) { if (begin == strArr.length - 1) {//begin等于最后一个字符位置结束递归 System.out.println(Arrays.toString(strArr)); } else { for (int i = begin; i < strArr.length; i++) { //1.把第一个字符与后边的所有字符交换 swap(strArr, begin, i); //2.固定第一个字符,对后边的所有字符全排列 permutation(strArr, begin + 1); //3.把交换到后边的字符交换回来 swap(strArr, begin, i); } } } /** * 交换数组中k1与k2位置的两个元素 * * @param arr * @param k1 * @param k2 */ private void swap(char[] arr, int k1, int k2) { char temp = arr[k1]; arr[k1] = arr[k2]; arr[k2] = temp; } }
上述的代码在字符不重复的情况下是正常的,如果出现重复字符例如"abcc",就会输出重复的排列情况。可以通过判断当前准备交换的字符,在begin字符前面的子字符串中是否出现过了,若出现了,就不交换,若没出现就交换。修改下上述方法。
/** * 字符串的全排列 */ public class Permutation { @Test public void testCase() { permutation("abcc"); } /** * 求字符串的全排列 * * @param str */ public void permutation(String str) { permutation(str.toCharArray(), 0); } /** * 求begin位置开始字符数组的排列 * * @param strArr 字符数组 * @param begin begin位置 */ private void permutation(char[] strArr, int begin) { if (begin == strArr.length - 1) {//begin等于最后一个字符位置结束递归 System.out.println(Arrays.toString(strArr)); } else { for (int i = begin; i < strArr.length; i++) { if (!isExist(strArr, begin, i)) { //1.把第一个字符与后边的所有字符交换 swap(strArr, begin, i); //2.固定第一个字符,对后边的所有字符全排列 permutation(strArr, begin + 1); //3.把交换到后边的字符交换回来 swap(strArr, begin, i); } } } } /** * isExist判断j位置的字符是否已经在list[0]~list[j-1]中出现过了 * list是含重复字符的数组,i是指示当前位置的游标,j是要判断的字符的位置 */ public boolean isExist(char[] arr, int i, int j) { for (int k = i; k < j; k++) { if (arr[j] == arr[k]) { return true; } } return false; } /** * 交换数组中k1与k2位置的两个元素 * * @param arr * @param k1 * @param k2 */ private void swap(char[] arr, int k1, int k2) { char temp = arr[k1]; arr[k1] = arr[k2]; arr[k2] = temp; } }
字符串组合
求n个字符中m个字符的组合的时候,可以把这n个字符分成两部分:第一个字符和其余的所有字符。如果组合里包含第一个字符,则下一步在剩余的字符里选取m-1个字符;如果组合里不包含第一个字符,则下一步在剩余的n-1个字符里选取m个字符,从中可以看出又是个递归的过程。/**
* 求字符串的组合
*/
public class Combination {
@Test
public void testCase() {
combination("abc");
}
/**
* 打印输入字符串包含的所有字符的所有组合
*
* @param str
*/
public void combination(String str) {
char[] arr = str.toCharArray();
for (int i = 1; i <= arr.length; i++) {
combination(arr, 0, i);
}
}
/**
* 存储组合的容器
*/
private Stack<Character> stack = new Stack<>();
/**
* 从begin位置开始,选取num个字符
*
* @param strArr
* @param begin
* @param num
*/
private void combination(char[] strArr, int begin, int num) {
if (num == 0) {
System.out.println(stack);
return;
}
if (begin >= strArr.length) {
return;
} else {
//把第一个字符放入组合中,在剩余的字符中选取num-1个字符
stack.push(strArr[begin]);
combination(strArr, begin + 1, num - 1);
//组合里不包含第一个字符,则下一步在剩余的字符中选取num个字符
stack.pop();
combination(strArr, begin + 1, num);
}
}
}
1、八皇后问题:在8*8的国际象棋上摆放八个皇后,使其任意两个皇后不能在同一行,同一列或者同一对角线上,求符合的摆法。
2、把8个数字分别放到正方体的8个顶点上,使正方体三组相对面上的四个定点的和都相等
上述两个问题都可以使8个数字全排列,分别进行判断是否符合上述条件
相关文章推荐
- 一个关于if else容易迷惑的问题
- 数据库链接字符串查询网站
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Flex字符串比较 还有Flex字符串操作
- Ruby实现的矩阵连乘算法
- Ruby中创建字符串的一些技巧小结
- ASP下经常用的字符串等函数参考资料
- 将字符串小写转大写并延时输出的批处理代码
- 将字符串转换成System.Drawing.Color类型的方法
- C#插入法排序算法实例分析
- Lua源码中字符串类型的实现
- Lua性能优化技巧(四):关于字符串
- 字符串聚合函数(去除重复值)
- Ruby中的字符串编写示例
- 总结的5个C#字符串操作方法分享
- sqlserver中求字符串中汉字的个数的sql语句
- 一道sql面试题附答案
- sql server字符串非空判断实现方法
- VBS的字符串及日期操作相关函数