排列和组合 Permutation and Combination
排列和組合 Permutation and Combination ---- Based on DFS and Backtracking
- Basic Concepts
- Permutation
- Combination
- Permutation
- Permutation --- Leetcode 46
- String Permutation --- Lintcode 10
- Combination
- Subsets (without duplicates) --- Leetcode 78
- Subsets II (with duplicates) --- Leetcode 90
- Summary
- Time Complexity of Combination and Permutation
Basic Concepts
Permutation
- A permutation of n distinct objects is an arrangment ( or ordering) of all n objects.
- Denoted as P(n)
- P(n) = n !
Example 1:
Suppose 10 students are sitting for a class picture. How many ways are there to arrange 10 students.
Answer: 10 * 9 *… * 2 * 1 = 10!
- An r-permutation n distinct objects is an arrangment (or ording) of r of the n objects.
- Denoted as P(n,r)
- P(n, r) = n! / (n-r)!
Example 1:
Suppose 10 students are sitting for a class picture. How many ways are there to arrange the row of 3 students.
Answer: 10 * 9 * 8 = 720
Combination
- An r-combination of n distinct objects is a selection (order doesn’t matter) of r of n objects. (Alson known as Sets)
- Denoted as C(n, r)
- C(n, r) = {n !} / {(n-r) ! r!}
Example 1:
How many 5 letters subsets can be made from 26 English letter.
Answer C(26, 5)
Example 2:
Calculate all subsets of number 12345
Answer = C(5,5) + C(5,4) + C(5,3) + C(5,2) + C(5,1) + C(5,0) = 25
Because for each digit, it has two options: choose or not choose
Therefore: 2 * 2 * 2 * 2 * 2
Permutation
Permutation — Leetcode 46
class Solution {public List<List<Integer>> permute(int[] nums) {List<List<Integer>> output = new ArrayList<List<Integer>>();List<Integer> tempList = new ArrayList<Integer>();return permutation(tempList, nums, output);}public List<List<Integer>> permutation(List<Integer> tempList, int [] nums, List<List<Integer>> output) {//output長度和數組長度一樣,代表本次排列完成,可以返回if (tempList.size() == nums.length) {output.add(new ArrayList(tempList));//output.add(tempList); 就不可以, 因為加入的是tempList的地址,所以之前加入的tempList會因為后面對tempList的改變而改變return output;}//對數組中每個元素進行遍歷for(int i = 0; i < nums.length; i++) {if (!tempList.contains(nums[i])) { //如果目前記錄的output里有num[i],則跳過此次循環(防止重復)tempList.add(nums[i]); //把當前元素加入outputpermutation(tempList, nums, output); //進行下一次循環, 完成dfstempList.remove(tempList.size()-1); //回到本層之后,刪除之前num[i],完成回溯}}return output;} }String Permutation — Lintcode 10
public class Solution {/*** @param str: A string* @return: all permutations*/public List<String> stringPermutation2(String str) {str = sortString(str);List<String> ans = new ArrayList<>();StringBuilder temp = new StringBuilder();boolean [] visited = new boolean[str.length()];dfs(visited, str, temp, ans);return ans;}public void dfs(boolean [] visited, String str, StringBuilder temp, List<String> ans) {if (temp.length() == str.length()) {//不能用注釋掉的方式去重,會超時/* if (!ans.contains(temp.toString())) {ans.add(temp.toString());}*/ ans.add(temp.toString());return;}for(int i = 0; i < str.length(); i++) {if (visited[i]) {continue;}//這里if的作用是去重: 不同位置的同樣的字符,必須按照順序用// a' a'' b// a' a'' b ok// a'' a' b not okif (i > 0 && str.charAt(i) == str.charAt(i-1) && !visited[i-1]) {continue;}temp.append(str.charAt(i));visited[i] = true;dfs(visited, str, temp, ans);visited[i] = false;temp = temp.deleteCharAt(temp.length()-1);}}public String sortString(String str) {char [] charArray = str.toCharArray();Arrays.sort(charArray);str = new String(charArray);return str;} }Combination
Subsets (without duplicates) — Leetcode 78
class Solution {public List<List<Integer>> subsets(int[] nums) {List<List<Integer>> ans = new ArrayList<>();List<Integer> temp = new ArrayList<>();if (nums.length == 0) {ans.add(new ArrayList<Integer>(temp));return ans;}dfs(ans, temp, nums, 0);return ans;}public void dfs(List<List<Integer>> ans, List<Integer> temp, int [] nums, int startIndex) {//將集合加入ans//用startIndex防止重復//take N to copy to ans listans.add(new ArrayList<Integer>(temp));for (int i = startIndex; i < nums.length; i++) { temp.add(nums[i]);dfs(ans, temp, nums, i + 1);//backtrackingtemp.remove(temp.size()-1);}} }Subsets II (with duplicates) — Leetcode 90
class Solution {public List<List<Integer>> subsetsWithDup(int[] nums) {Arrays.sort(nums); //must sort in order to skip all the duplicate subsetsList<List<Integer>> ans = new ArrayList<>();List<Integer> temp = new ArrayList<>();dfs(nums, ans, temp, 0);return ans;}public void dfs(int [] nums, List<List<Integer>> ans, List<Integer> temp, int startIndex) {ans.add(new ArrayList<Integer>(temp));for(int i = startIndex; i < nums.length; i++) {// skip all the duplicate//if the current number is same as previous one, then skip//Exception: if the previous number is the startIndex ( i > startIndex )//Example: a b' b'' b''' d//startIndex: 1//a b' b'' d ok//a b' b''' d not okif ( i > startIndex && nums[i-1] == nums[i]) {continue;}temp.add(nums[i]);dfs(nums, ans, temp, i + 1);temp.remove(temp.size() - 1); //backtracking}} }Summary
- Examples shown above are template for solving all combination and permutation problems.
- Combination needs startIndex, Permutations doesn’t need startIndex
- For handling duplicated elements in input:
Combination:
if ( i > startIndex && nums[i-1] == nums[i]) { continue; }
Permutation:
if (i > 0 && str.charAt(i) == str.charAt(i-1) && !visited[i-1]) { continue; }
Time Complexity of Combination and Permutation
- Combination — Subsets problem (Leetcode 78)
2n * n : A total of 2n possibilities and each possibility takes N to copy to the ans list
Why 2n: for example, for string 12345, each number has an option of choose or not choose, therefore 2n - Permutation — Permutation problem (Leetcode 46)
n! * n: A total of n! possibilities and each possibility takes N to copy to the ans list
General formula for DFS:
Number of possibilities * Time to create each possibility
總結
以上是生活随笔為你收集整理的排列和组合 Permutation and Combination的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】 笔记本散热维护
- 下一篇: 11gR2 RAC vip和networ