LeetCode 刷题记录 47.PermutationsII

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

Example:

Input: [1,1,2]
Output:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
这次有重复需要去重,46题的解法1和解法2无需修改仍可使用
解法1:
调用函数next_permutation
首先输入的序列不一定是排序好的,首先要先排序,注意使用do while 结构,第一个排列也要加进去
c++:

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
        do{
            res.push_back(nums);
        } while(next_permutation(nums.begin(),nums.end()));
        return res;
    }
};

解法2:
LeetCode 刷题记录31. 31. Next Permutation的函数
函数需要点改进,原函数没有返回数据,现在我们需要返回true或者false,表示是否结束

  1. 如果排列为1位,自然没有下一个排列,返回false
  2. 如果最后需要整个反转即说明到达了最后一个排列,如3 2 1 ,不需要再进行了,返回false
    c++:
class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
        do{
            res.push_back(nums);
        } while(nextPermutation(nums));
        return res;
    }
    bool nextPermutation(vector<int>& nums) {
        int n = nums.size();
        if(n <= 1) return false;
        int i = n - 2;
        int j = n - 1;
        while(i >= 0 && nums[i] >= nums[i + 1]) --i;
        if(i >= 0){
            while(j >= 0 && nums[j] <= nums[i]) --j;
            swap(nums[i] , nums[j]);
        }
        if(i == -1){
            //reverse(nums.begin(), nums.end());
            return false;
        } else {
            reverse(nums.begin() + i + 1 , nums.end());
            return true;
        }
        
    }


};

java:
java需要将int[] 数组转成List list,详见Java:ArrayList和数组int[]的相互转化

class Solution {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        List<Integer> list = null;
        do{
            list = Arrays.stream(nums).boxed().collect(Collectors.toList());
            res.add(list);
        } while(nextPermutation(nums));
        return res;
    }
    public boolean nextPermutation(int[] nums) {
        int n = nums.length;
        if(nums == null || n <= 1) return false;
        int i = n - 2;
        int j = n - 1;
        while(i >= 0 && nums[i] >= nums[i + 1]) --i;
        if(i >= 0){
            while(j >= 0 && nums[j] <= nums[i]) --j;
            swap(nums, i, j);
        }
        if(i == -1){
            //reverse(nums, 0 , n - 1);
            return false;
        } else {
            reverse(nums, i + 1 , n - 1);
            return true;
        }
        
    }
    private void reverse(int[] nums, int start, int end){
        int i = start;
        int j = end;
        while(i < j){
            swap(nums, i, j);
            i++;
            j--;
        }
    }
    private void swap(int[] nums, int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

}

python:

  1. python中没有do while 函数
  2. append函数添加nums时,添加的是引用,所以后面添加的会改变前面的元素,所以要用深拷贝append操作被覆盖 ,此外可以用res.append(nums[:])来创建新的对象
class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        nums.sort()
        temp = copy.deepcopy(nums)
        res.append(temp)   
        
        while self.nextPermutation(nums):
            temp = copy.deepcopy(nums)
            res.append(temp)
            
            
        return res
    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        if nums == None or n <= 1: return False
        i = n - 2
        j = n - 1
        while i >= 0 and nums[i] >= nums[i + 1]: i -= 1
        if i >= 0:
            while j >= 0 and nums[j] <= nums[i]: j -= 1
            nums[i] , nums[j] = nums[j], nums[i]
        if i == -1:
           
            return False
        else:
            start = i + 1
            end = n - 1
            while start < end:
                nums[start] , nums[end] = nums[end], nums[start]
                start, end = start + 1, end - 1
           
            return True
        

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        nums.sort()
        temp = copy.deepcopy(nums)
        res.append(temp)   
        print res
        while self.nextPermutation(nums):
            # temp = copy.deepcopy(nums)
            # res.append(temp)
            res.append(nums[:])
            
            
        return res
    def nextPermutation(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        if nums == None or n <= 1: return False
        i = n - 2
        j = n - 1
        while i >= 0 and nums[i] >= nums[i + 1]: i -= 1
        if i >= 0:
            while j >= 0 and nums[j] <= nums[i]: j -= 1
            nums[i] , nums[j] = nums[j], nums[i]
        if i == -1:
            start = i + 1
            end = n - 1
            while start < end:
                nums[start] , nums[end] = nums[end], nums[start]
                start, end = start + 1, end - 1
            print nums
            return False
        else:
            start = i + 1
            end = n - 1
            while start < end:
                nums[start] , nums[end] = nums[end], nums[start]
                start, end = start + 1, end - 1
           
            return True
        

解法3:
与46题的不同,首先需要排序,然后需要
if(i > 0 && nums[i] == nums[i-1] && visited[i-1] == 0) continue;
来去重,解释见[LeetCode] 47. Permutations II 全排列之二
注意:

  1. 不能不加visited[i-1] == 0,如果不加这个条件 如 1 2a 2b,当结果已经有1 2a,再加入2b时便不能加入了,显然是错的
  2. 条件visited[i-1] == 0或者visited[i-1] == 1都可以
    前者 结果有1 2a ,再加入2b,此时visited[1] == 1可以加入
    但是当2a出栈,回退时此时visited[1] == 0,结果1 ,不能加入2b
    后者 结果有1 2a ,此时visited[1] == 1,不可以加入2b
    但是当2a出栈,回退时此时visited[1] == 0,结果1 ,能加入2b,进而继续加入2a

显然前者效率更高
c++:

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
         vector<vector<int>> res;
        int n = nums.size();
        vector<int> path,visited(n, 0);
        sort(nums.begin(),nums.end());
        DFS(nums, path, visited,res,0);
        return res;


    }
   void DFS(vector<int>& nums,vector<int>& path,vector<int>& visited,vector<vector<int>>& res,int index) {
        if(index == nums.size()){
            res.push_back(path);
            return;
        }
        for(int i = 0; i < nums.size(); i++){
            
            if(visited[i] == 1) continue;
            if(i > 0 && nums[i] == nums[i-1] && visited[i-1] == 0) continue;
            //if(i > 0 && nums[i] == nums[i-1] ) continue;
            //cout << nums[i] << " " << i << " "<<index<<endl;
            path.push_back(nums[i]);
            visited[i] = 1;
            DFS(nums, path, visited,res,index + 1);
            path.pop_back();
            visited[i] = 0;
            
        }
    }


};

java:

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>>  res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        boolean[] visited = new boolean[nums.length];
        Arrays.sort(nums);
        DFS(nums, path, res, visited, 0);
        return res;


    }
    private void DFS(int[] nums,List<Integer> path,List<List<Integer>> res,boolean[] visited,int index){
        
        
        if(index == nums.length){
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i = 0; i < nums.length; ++i){
            if(visited[i] == true) continue;
            if(i > 0 && nums[i] == nums[i-1] && visited[i-1] == false) continue;
            path.add(nums[i]);
            visited[i] = true;
            DFS(nums, path, res,visited , index + 1);
            path.remove(path.size() - 1);
            visited[i] = false;
        }
        
    }

   

}

python:

class Solution(object):
    def permuteUnique(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        path = []
        visited = [0] * len(nums)
        nums.sort()
        self.DFS(nums, path, res, visited, 0)
        return res
    def DFS(self, nums, path, res,visited,index):
        
        if index == len(nums):
           
            res.append(path)
            return
        for i in xrange(len(nums)):
            
            
            if visited[i] == 1: continue
            if i > 0 and nums[i] == nums[i-1] and visited[i-1] == 0: continue
            visited[i] = 1
           
            self.DFS(nums, path + [nums[i]], res, visited, index + 1)
            #self.DFS(nums, path, res, visited, index + 1)
            visited[i] = 0


解法4:
递归法(交换)
用一个set记录已经交换过的,如有重复则不进行交换
如第一行:1和1自己交换,记录1,1和2a交换,记录2a,将要1和2b交换,发现set中已经有2a,则不进行交换,避免了重复
可以提前进行排序,也可以不用,提前排序效率高一点
在这里插入图片描述
c++

class Solution {
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
        DFS(nums, res,0);
        return res;


    }
   void DFS(vector<int>& nums,vector<vector<int>>& res,int start) {
        if(start == nums.size()){
            res.push_back(nums);
            return;
        }
        set<int> s;
        for(int i = start; i < nums.size(); i++){
            if(s.count(nums[i]) != 0) continue;
            s.insert(nums[i]);
            swap(nums[start], nums[i]);
        
            DFS(nums,res,start + 1);
            swap(nums[start], nums[i]);
            
        }
   }


};
class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>>  res = new ArrayList<>();
        Arrays.sort(nums);
        DFS(nums, res, 0);
        return res;


    }
    private void DFS(int[] nums,List<List<Integer>> res,int start){
        if(start == nums.length){
            
            List<Integer> temp = new ArrayList<Integer>(); 
            for (int i = 0; i < nums.length; i++) {
                temp.add(nums[i]);
            }
            res.add(new ArrayList<>(temp));
            return;
        }
        Set<Integer> st = new HashSet<>();
        for(int i = start; i < nums.length; ++i){
            if(st.contains(nums[i])) continue;
            st.add(nums[i]);
            swap(nums,start,i);
            
            
           
            DFS(nums, res, start + 1);
            
            swap(nums,start,i);
            
        }
        
    }
    private void swap(int[] nums, int i, int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
     




}

python:

class Solution(object):
    def permuteUnique(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums.sort()
        res = []
        self.DFS(nums, res, 0)
        return res
    def DFS(self, nums,  res,start):
        
        if start == len(nums):
           
            res.append(nums[:])
            return
        s = set()
        for i in xrange(start,len(nums)):
            if nums[i] in s: continue
            s.add(nums[i])
            nums[start], nums[i] =  nums[i],nums[start]
            self.DFS(nums,  res, start + 1)
            nums[start], nums[i] =  nums[i],nums[start]


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值