LeetCode:全排列II【47】

LeetCode:全排列II【47】

参考自天码营题解:https://www.tianmaying.com/tutorial/LC47

题目描述

给定一个可包含重复数字的序列,返回所有不重复的全排列。

示例:

输入: [1,1,2]
输出:
[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

题目分析

  这道题与上一道全排列I的区别在于,这一次给的序列可以包含重复元素。

  1、那此时我们怎么判断当前元素是否使用过呢?

    我们使用BitMap(位图)技术建立一个和序列长度相等的布尔数组,记录每一个位置的元素是否使用过就可以了。这样,无疑会遍历到每一个不同的排列,但是也存在着问题,以样例为例,[1,1,2]这样的排列会被遍历到许多次,这就导致最后输出的答案存在着重复

  2、如何解决这样的重复呢?

    我们先看看这样的重复是如何产生的,不难发现,[1,1,2]在之前描述的回溯中会枚举2次。如果不用数值而是用这个数在nums中的下标来表示的话,[1,1,2]被枚举的两次分别是[0,1,2]和[1,0,2],即下标为0的“1”和下标为1的“1”在枚举的过程中被考虑成了两个不同的选择,但是在最后的答案中却没有什么不同。

    而这样产生的重复也非常好解决,就是对于一个位置的同一个取值,只枚举一次,也就是如果已经在第1个位置上枚举了“1”这个数字,那么即使之后仍然有“1”的取值,也都跳过不进行枚举

     在实际的实现中,我们不妨这样枚举,即将nums数组排序后,只有nums[i]不等于nums[i-1]时,才将nums[i]视作一种可能的取值,即:

for (int i = 0; i < nums.size(); i++) {
    // 确保在一个位置不会枚举两个相同的数
    if (i == nums.size() - 1 || nums[i] != nums[i-1]) {

    }
}

    这样,就可以保证[1,1,2]在最终的方案中只被计算一次,即同一个取值的元素只取最左边的

    特别的,当加入了used[]数组用于判断一个数字是否被使用过之后,由于每次使用的一定是所有相同数字中最左侧的一个,所以对于一个取值,如果它左侧的数字是已经被使用过了的,就同样说明这个数是当前所有相同数字中最左侧的可用的了,即:

for (int i = 0; i < nums.size(); i++) if (!used[i]) {
    // 确保在一个位置不会枚举两个相同的数
    if (i == nums.size() - 1 || nums[i] != nums[i - 1] || used[i - 1]) {

    }
}

  我的解法比较简单,没有利用排序,也没有跳过策略,只是在最后放入结果集的时候,检测是否有排列的元素出现过,这将会导致很多无意义的递归过程。

高效解法

public List<List<Integer>> permuteUnique(int[] nums) {
    List<List<Integer>> list = new ArrayList<>();
    Arrays.sort(nums);
    backtrack(list, new ArrayList<>(), nums, new boolean[nums.length]);
    return list;
}

private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums, boolean [] used){
    if(tempList.size() == nums.length){
        list.add(new ArrayList<>(tempList));
    } else{
        for(int i = 0; i < nums.length; i++){
            if(used[i] || i > 0 && nums[i] == nums[i-1] && !used[i - 1]) continue;
            used[i] = true;
            tempList.add(nums[i]);
            backtrack(list, tempList, nums, used);
            used[i] = false;
            tempList.remove(tempList.size() - 1);
        }
    }
}

Java题解

class Solution {
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        backtrack(lists,new ArrayList<>(),new boolean[nums.length],nums);
        return lists;
    }

    public  void backtrack(List<List<Integer>> lists,List<Integer> tmpList,boolean[] visited,int[] nums)
    {
        if(tmpList.size()==nums.length&&!lists.contains(tmpList))
            lists.add(new ArrayList<>(tmpList));
        else
            for(int i=0;i<nums.length;i++)
            {
                if(visited[i])
                    continue;
                visited[i]=true;
                tmpList.add(nums[i]);
                backtrack(lists,tmpList,visited, nums);
                visited[i]=false;
                tmpList.remove(tmpList.size()-1);
            }
    }
} 

原文地址:https://www.cnblogs.com/MrSaver/p/9938724.html

时间: 2024-11-14 17:55:20

LeetCode:全排列II【47】的相关文章

[leetcode] 47. 全排列 II

47. 全排列 II 比上一个题多了个重复性 与46. 全排列完全一样的代码... class Solution { // 当没有下一个排列时return false public boolean nextPermutation(int[] nums) { if (nums.length == 1) { return false; } int p = -1; for (int i = nums.length - 2; i >= 0; i--) { if (nums[i] < nums[i +

[LeetCode] 267. Palindrome Permutation II 回文全排列 II

Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form. For example: Given s = "aabb", return ["abba", "baab"]. Given s = "a

LeetCode OJ--Permutations II

给的一个数列中,可能存在重复的数,比如 1 1  2 ,求其全排列. 记录上一个得出来的排列,看这个排列和上一个是否相同. #include <iostream> #include <vector> #include <algorithm> using namespace std; class Solution{ public: vector<vector<int> > permuteUnique(vector<int> &n

[leetcode]Subsets II @ Python

原题地址:https://oj.leetcode.com/problems/subsets-ii/ 题意: Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicat

LeetCode: N-Queens II [051]

[题目] Follow up for N-Queens problem. Now, instead outputting board configurations, return the total number of distinct solutions. [题意] 解N皇后问题,N-Queens要求返回所有的解,而本题只需要返回可行解的数目 [思路] DFS,参考N-Queens [代码] class Solution { public: bool isValid(vector<string

LeetCode: Permutations II [046]

[题目] 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]. [题意] 给定一个候选数集合,候选集中可能存在重复数,返回所有的排列 [思路] 思路和Permutat

LeetCode: Subsets II [091]

[题目] Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,2], a solutio

[LeetCode] Subsets II [32]

题目 Given a collection of integers that might contain duplicates, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,2], a solution

Leetcode: N-Queens II C++

class Solution { public: int totalNQueens(int n) { //initialize chessboard vector<vector<bool>> boardconf; vector<bool> orig_row; orig_row.assign(n,false); boardconf.assign(n,orig_row); int totalNum = 0; for(int j = 0; j < n; j++){ to