算法 排列、组合 相关
来源:互联网 发布:linq.js where 编辑:程序博客网 时间:2024/05/17 21:54
字符串的去重全排列
public class Permutation { public static void main(String[] args) { String s = "abc"; permutation(s.toCharArray(), 0); } /* 从第一个字符起,挨个与后面每个字符交换。 */ private static void permutation(char[] chars, int start) { if (chars == null || chars.length == 0) return; if (start == chars.length - 1) { System.out.println(chars); } else { for (int i = start, length = chars.length; i < length; ++i) { if (isSwap(chars, start, i)) { CommonUtil.swap(chars, i, start); permutation(chars, start + 1); CommonUtil.swap(chars, i, start); } } } } // 与它后面非重复出现的数字交换 private static boolean isSwap(char[] chars, int start, int end) { for (int i = start; i < end; ++i) { if (chars[i] == chars[end]) { return false; } } return true; }}
八皇后问题
/** * 八皇后问题: * 在8×8的国际象棋上摆放八个皇后,使其不能相互攻击, * 即任意两个皇后不得处在同一行、同一列或者同一对角斜线上。 * * 求出总共有多少种摆法 */public class EightQueue { public static void main(String[] args) { int[] arr = new int[]{0, 1, 2, 3, 4, 5, 6, 7}; sortQueue(arr, 0); } /* 在[0,8)的数组上,第i个位置上的数字j表示(第i行,第j列) 0 <= i < 8 0 <= j < 8 即j的全排列,每个i上可以放置[0,8)个数字, 8! 共有8!种方法,排除掉: 处于同一行的 --> 不可能,在设置的时候就有8个位置了 处于同一列的 --> 任意两个i上的数字相同,也是不可能的 任意两个皇后处于同一对角线的 --> 间距相等了 */ private static void sortQueue(int[] arr, int start) { if (start == arr.length - 1) { // 过滤 if (isDiagonal(arr)) { // 是对角线的不输出 return; } CommonUtil.printArray(arr); } else { for (int i = start, length = arr.length; i < length; ++i) { CommonUtil.swap(arr, start, i); sortQueue(arr, start + 1); CommonUtil.swap(arr, start, i); } } } private static boolean isDiagonal(int[] arr) { for (int i = 0, length = arr.length; i < length; ++i) { for (int j = i + 1; j < length; ++j) { if (arr[i] - arr[j] == i - j || arr[i] - arr[j] == j - i) { return true; } } } return false; }}
字符串的组合
/** * <p> * 输入一个字符串,输出该字符串中字符的所有组合。 * 举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。 */public class Combination { /* 2^n -1 个 */ public static void main(String[] args) { String s = "abc"; combination_bit(s.toCharArray()); // 位运算 combination(s.toCharArray()); // 递归 } /* 共有 2^n -1 中组合 使用位运算, 001表示a, 010表示b, 100表示c 遍历 [1, 2^n) 个数字,对每个数字进行位运算,找出所有组合 O(2^n) 指数级 */ private static void combination_bit(char[] chars) { if (chars == null || chars.length == 0) return; int length = chars.length; int n = 1 << length; StringBuilder builder = new StringBuilder(); for (int i = 1; i < n; ++i) { for (int j = 0; j < length; ++j) { if ((i & (1 << j)) != 0) { // 001 010 100 builder.append(chars[j]); } } System.out.println(builder.toString()); builder.delete(0, builder.length()); } } /* 在长度为n的字符串中求m个字符的组合, 1 <= m <= n。我们先从头扫描字符串的第一个字符。 针对第一个字符,我们有两种选择: 第一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符; 第二是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。 这两种选择都很容易用递归实现。 */ private static void combination(char[] chars) { if (chars == null || chars.length == 0) return; Stack<Character> stack = new Stack<>(); for (int i = 1, length = chars.length; i <= length; ++i) { combination(chars, 0, i, stack); } } /* start指扫描到哪个字符了 number是指几位组合, 1位组合还是m位组合 */ private static void combination(char[] chars, int start, int number, Stack<Character> stack) { if (number == 0) { System.out.println(stack.toString()); return; } if (start == chars.length) { return; } stack.push(chars[start]); combination(chars, start + 1, number - 1, stack); stack.pop(); combination(chars, start + 1, number, stack); }}
组合习题一
/** * 输入两个整数n和m, * 从数列1,2,3...n中随意取几个数,使其和等于m,要求列出所有的组合。 */public class EqualsMCombination { public static void main(String[] args) { // 找出所有组合,输出和为m的组合 findSumIsM(5, 12); System.out.println(); System.out.println(); // 以和为target寻找 findSumIsM_Simple(5, 12); } /* 从最大值开始开始寻找,即从n开始 对于每个n,都有两种选择: 1. 将即计入和m中,在剩下的n-1个数字中继续寻找和为 n-m 的数字 2. 不计算于其中,在剩下的 n-1 个数字中寻找和为m 的数字 终止条件: m==0(找完了) n<0 || m<0 (找不到) */ private static void findSumIsM_Simple(int n, int m) { if (m > ((1 + n) * n / 2)) { System.out.println("m太大了"); } Stack<Integer> stack = new Stack<>(); findIt_Simple(n, m, stack); } private static void findIt_Simple(int n, int m, Stack<Integer> stack) { if (n < 0 || m < 0) { return; } if (m == 0) { System.out.println(stack); return; } stack.push(n); findIt_Simple(n - 1, m - n, stack); stack.pop(); findIt_Simple(n - 1, m, stack); } /* [1,n] 中,获取所有的组合,输出和为m的组合 分两步: 1. 获取所有组合 (就可以使用之前字符串组合的方式) 2. 输出所有和为m的组合 在n个数字中选取m个数字(1<=m<=n), 从1开始遍历数列,针对第一个数字: 将这个数字放到组合中,在剩下的 n-1个 数字中选取m - 1个 不把这个数字放到组合中,在剩下的 n-1 个 数字中选取m个 */ private static void findSumIsM(int n, int m) { if (m > ((1 + n) * n / 2)) { System.out.println("没有满足的序列,超过所有数字之和"); } Stack<Integer> stack = new Stack<>(); for (int i = 1; i <= n; ++i) { findIt(n, 1, i, stack, m); } } private static void findIt(int n, int start, int number, Stack<Integer> stack, int targetSum) { if (number == 0) { int sum = 0; for (Integer integer : stack) { sum += integer; } if (sum == targetSum) { System.out.println(stack); } return; } if (start == n + 1) { return; } stack.push(start); findIt(n, start + 1, number - 1, stack, targetSum); stack.pop(); findIt(n, start + 1, number, stack, targetSum); }}
组合习题二
就是一个特殊情况
/** * Given two integers n and k, * return all possible combinations of k numbers out of 1 ... n. * <p> * 从[1...n]中选取k个数的所有组合 */public class LimitedCombination { public static void main(String[] args) { int n = 5; int k = 2; Stack<Integer> stack = new Stack<>(); combination(n, 0, k, stack); } /* 从n个数中选取k个数,从第一个数开始 1) 选择将其放入组合内,从剩下的 n-1 个数中选取 k-1 个数 2) 不将其放入组合内,从剩下的 n-1 个数中 选取 k 个数 */ private static void combination(int n, int start, int number, Stack<Integer> stack) { if (number == 0) { System.out.println(stack); return; } if (start == n + 1) { return; } stack.push(start); combination(n, start + 1, number - 1, stack); stack.pop(); combination(n, start + 1, number, stack); }}
参考:
字符串的全排列和组合算法
July 算法习题 - 字符串4(全排列和全组合)
阅读全文
0 0
- 算法 排列、组合 相关
- 常用排列与组合的相关算法
- 排列、组合相关知识
- 排列、组合及算法
- 排列、组合及算法
- 排列 组合 算法 C#
- 快速组合排列算法
- 排列与组合算法
- 排列与组合算法
- 组合全排列算法
- 排列和组合算法
- java组合排列算法
- 组合排列的通用算法
- 组合排列的javascript算法
- 排列 组合 算法(一)
- 排列与组合的算法
- 【算法基础】排列与组合
- java求组合排列算法
- (map+struct)GYM_100443 Trending Topic
- 垃圾收集器与内存分配策略
- 子矩阵
- 2017.08.14【NOIP提高组】模拟赛B组总结
- QNX加密方法-qnx防破解-增加安全功能
- 算法 排列、组合 相关
- 信号和槽
- ZOJ 3747 Attack on Titans【带限制条件的递推dp+计数技巧】
- 【笔记】NEXUS 3.* 下载及安装, 与2.*稍有不同
- H3C笔试题:C语言旋转双向链表
- testng.xml文件结构
- yii 里sphinx使用
- Qt的元对象系统
- #ifdef #endif