Skip to content

Latest commit

 

History

History
91 lines (71 loc) · 2.48 KB

47 Permutations II.md

File metadata and controls

91 lines (71 loc) · 2.48 KB

47. Permutations II

##Problem

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example, [1,1,2] have the following unique permutations: [1,1,2], [1,2,1], and [2,1,1].

tags:

  • backtracking
  • 包含重复元素的全排列

Solution

参考:《组合数学》

  • 直接生成(递归/回溯)
  • 邻位互换
  • 序数法
  • 字典序法
  • 轮转法

递归

参考全排列的递归公式(46 Permutations.md),以重复元素作为前缀的均算作一个排列
即:

n=1 排列为自身
n>1 Pn = iPi (i为序列中不重复的元素,Pi表示以i作为前缀的全排列)

java

public class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        recur(res, nums, 0, nums.length);
        return res;
    }
    
    void recur(List<List<Integer>> res, int[] nums, int begin, int end) {
        if(begin==end) {
            List<Integer> li = new ArrayList<Integer>(nums.length);
            for(Integer num:nums) {
                li.add(num);
            }
            res.add(li);
        } else {
            for(int i=begin;i<end;i++) {
                if(isSwap(nums, begin, i)) {
                    swap(nums, begin, i);
                    recur(res, nums, begin+1, end);
                    swap(nums, begin, i);
                }
            }
        }
    }
    
    void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j]=tmp;
    }
    
    boolean isSwap(int[] nums, int begin, int end){
        for(int i=end; i>begin; i--) {
            if(nums[end]==nums[i-1]) {
                return false;
            }
        }
        return true;
    }
}

字典序法

字典序:
对于两个序列 a1...ak和b1...bk,若存在t,使得ai=bi,at < bt,则序列
a1...ak < b1...bk

生成算法

设P是1...n的一个全排列,P = P1P2...Pj-1PjPj+1...Pk-1PkPk+1...Pn

  1. 找出j=max{i|Pi < Pi+1}, k=max{i|Pi <=> Pj}
  2. 对换Pj,Pk
  3. Pj+1...Pk-1PkPk+1...Pn

未完待续。。。