排列和组合 Permutation and Combination

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]); //把当前元素加入output
                permutation(tempList, nums, output); //进行下一次循环, 完成dfs
                tempList.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 ok
            if (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 list
        ans.add(new ArrayList<Integer>(temp));
        
        for (int i = startIndex; i < nums.length; i++) { 
            temp.add(nums[i]);
            dfs(ans, temp, nums, i + 1);
            //backtracking
            temp.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 subsets
        List<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 ok
            if ( 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:
  1. Sort Input
  2. Add following code in for loop

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值