zoukankan      html  css  js  c++  java
  • 47. Permutations II

    这个比一般的backtrack要难一点,有2个限制因素。

    某个元素在某次递归中只能用一次。

    重复。

    主要就是这2个因素。

    先SORT一下。

    用visited[]记录哪个元素用过,用过直接跳过。

    然后每个递归里,除了第一个元素之外,不许重复。

    if(i != 0 && nums[i] == nums[i-1] && visited[i-1]) continue;
    

    剩下的就是比较基础的backtrack了,记得每次要把visited恢复。

    public class Solution {
        public List<List<Integer>> permuteUnique(int[] nums) 
        {
            List<List<Integer>> res = new ArrayList<List<Integer>>();
            if(nums.length == 0) return res;
            
            Arrays.sort(nums);
            boolean[] visited = new boolean[nums.length];
            
            
            helper(res,nums,new ArrayList<Integer>(),visited);
            
            return res;
        }
        
        public void helper(List<List<Integer>> res, int[] nums, List<Integer> tempList, boolean[] visited)
        {
            if(tempList.size() == nums.length)
            {
                res.add(tempList);
            }
            else
            {
                for(int i = 0; i < nums.length; i++)
                {
                    if(i != 0 && nums[i] == nums[i-1] && visited[i-1]) continue;
                    
                    if(!visited[i])
                    {
                        visited[i] = true;
                        tempList.add(nums[i]);
                        
                        helper(res,nums,new ArrayList<>(tempList),visited);
                        
                        tempList.remove(tempList.size()-1);
                        
                        
                        
                        visited[i] = false;
                    }
                }
                
                
            }
            
        }
    }
    

    这不是重点。。重点是有个用SWAP的方法,46 47都可以那么做。研究一下。。

    public class Solution {
        public List<List<Integer>> permuteUnique(int[] nums) 
        {
            List<List<Integer>> res = new ArrayList<List<Integer>>();
            if(nums.length == 0) return res;
            
            Arrays.sort(nums);
            
            
            
            helper(res,nums,0);
            
            return res;
        }
        
        public void helper(List<List<Integer>> res, int[] nums, int m)
        {
            if(m == nums.length)
            {
                List<Integer> tempList = new ArrayList<>();
                for(int n: nums) tempList.add(n);
                res.add(new ArrayList<>(tempList));
            }
            
            else
            {
                Set<Integer> set = new HashSet<Integer>();
                for(int i = m; i < nums.length;i++)
                {
                    if(set.add(nums[i]))
                    {
                        swap(i,m,nums);
                        helper(res,nums,m+1);
                        swap(i,m,nums);
                    }
                   
                }
            }
            
        }
        
        public void swap(int i,int j,int[] nums)
        {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }
    }
    

    思路是这样的,拿1 2 3。

    先看2 3。 23是一种,交换一下32是一种。
    然后看1,1和2换 后面变成13,又有2种;1和3换,后面是12,又有2种。

    假如前面再有个0,0又要分别和123来换。

    简单地说,每个数都可以在每一个位上来一发。

    这里循环进的M其实是位置,M后面的每个数都可以过来感受一下。。

    很抽象。

    46也可以这么做。



    二刷。

    还是DFS,不过有重复,那重点就是去重了。
    同样深度的情况下,出现重复的,那么需要跳过。 具体说就是:
    判断是否和上一个相等,相等的情况下如果上一个没用过,说明是上一个回溯结束的,同一层,那么就不要再重新来一轮了,跳过。 112 分别以1,1,2开始,第二个1,和第一个1开始的结果重复的。
    在第一个1开始的时候,下一层的当前元素是第二个1,虽然也是1,但是上一个1被用了,说明它是不同深度的,所以不跳过。

    public class Solution {
        public List<List<Integer>> permuteUnique(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            boolean[] visited = new boolean[nums.length];
            Arrays.sort(nums);
            dfs(res, visited, nums, new ArrayList<>());
            return res;
        }
        
        public void dfs(List<List<Integer>> res, boolean[] visited, int[] nums, List<Integer> tempList) {
            if (tempList.size() == nums.length) {
                res.add(tempList);
            } else {
                for (int i = 0; i < nums.length; i++) {
                    if (i != 0 && nums[i] == nums[i-1] && !visited[i-1]) continue;
                    if (!visited[i]) {
                        visited[i] = true;
                        tempList.add(nums[i]);
                        dfs(res, visited, nums, new ArrayList<>(tempList));
                        tempList.remove(tempList.size() - 1);
                        visited[i] = false;
                    }    
                }
            }
        }
    }
    
  • 相关阅读:
    手把手教你利用create-nuxt-app脚手架创建NuxtJS应用
    初识NuxtJS
    webpack打包Vue应用程序流程
    用选择器代替表格列的筛选功能
    Element-UI
    Spectral Bounds for Sparse PCA: Exact and Greedy Algorithms[贪婪算法选特征]
    Sparse Principal Component Analysis via Rotation and Truncation
    Generalized Power Method for Sparse Principal Component Analysis
    Sparse Principal Component Analysis via Regularized Low Rank Matrix Approximation(Adjusted Variance)
    Truncated Power Method for Sparse Eigenvalue Problems
  • 原文地址:https://www.cnblogs.com/reboot329/p/6053808.html
Copyright © 2011-2022 走看看