zoukankan      html  css  js  c++  java
  • 与回溯相关的力扣练习题总结

    46.排列

    给定一个不含重复数字的数组 nums ,返回其所有可能的全排列 。你可以按任意顺序返回答案。

    private List<List<Integer>> resList;
    public List<List<Integer>> permute(int[] nums) {
    
        if (nums == null || nums.length == 0){
            return new ArrayList<>();
        }
    
        int n = nums.length;
        boolean[] visited = new boolean[n];
        resList = new ArrayList<>();
    
        for (int i = 0; i < nums.length; i++) {
            findByDFS(nums,new ArrayList<Integer>(),visited,i);
        }
    
        return resList;
    }
    
    
    private void findByDFS(int[] nums,List<Integer> list,boolean[] visited,int index){
    
        if (visited[index]){
            return;
        }
    
        list.add(nums[index]);
        visited[index] = true;
    
        for (int i = 0; i < nums.length; i++) {
            if (!visited[i])
                findByDFS(nums,list,visited,i);
        }
    
        if (list.size() == nums.length){
    
            resList.add(new ArrayList<>(list));
        }
    
        list.remove(list.size()-1);
        visited[index] = false;
    }
    

    47.含有相同元素求排列

    给定一个可包含重复数字的序列 nums按任意顺序返回所有不重复的全排列。

    private List<List<Integer>> resList;
    public List<List<Integer>> permuteUnique(int[] nums) {
    
        if (nums == null || nums.length == 0){
            return new ArrayList<>();
        }
    
        int n = nums.length;
        Arrays.sort(nums);
        boolean[] visited = new boolean[n];
        resList = new ArrayList<>();
    
        for (int i = 0; i < n; i++) {
            if (i != 0 && nums[i] == nums[i-1] && !visited[i-1]){
                continue;
            }
            findByDFS(nums,visited,i,new ArrayList<>());
        }
    
        return resList;
    }
    
    private void findByDFS(int[] nums,boolean[] visited,int index,List<Integer> list){
    
        if (visited[index]){
            return;
        }
    
        list.add(nums[index]);
        visited[index] = true;
    
        for (int i = 0; i < nums.length; i++) {
    
            if (i != 0 && nums[i] == nums[i-1] && !visited[i-1]){
                continue;
            }
    
            if (!visited[i])
                findByDFS(nums,visited,i,list);
        }
    
        if (list.size() == nums.length){
            resList.add(new ArrayList<>(list));
        }
    
        visited[index] = false;
        list.remove(list.size()-1);
    }
    

    77.组合

    给定两个整数nk,返回 1 ... n 中所有可能的 k 个数的组合。1...n中的数字只能取一次。

       private List<List<Integer>> resList;
       public List<List<Integer>> combine(int n, int k) {
    
            if (k == 0){
                return new ArrayList<>();
            }
            
            resList = new ArrayList<>();
            findGroupByDFS(n,new ArrayList<>(),k,1);
            return resList;
       }
        
       private void findGroupByDFS(int n,List<Integer> list,int k,int start){
    
            if (list.size() == k){
    
                resList.add(new ArrayList<>(list));
                return;
            }
            // (n - (k-list.size())+1)就表示当前的组合序列中的第(list.size() + 1)个数可以从1..n中选取值的范围
            for (int i = start; i <= (n - (k-list.size())+1); i++) {
    
                list.add(i);
                findGroupByDFS(n,list,k,i+1);
                list.remove(list.size()-1);
            }
       }
    

    39.组合总和

    给定一个无重复元素的数组candidates和一个目标数target ,找出candidates中所有可以使数字和为target的组合。

    candidates 中的数字可以无限制重复被选取。

    说明:

    • 所有数字(包括 target)都是正整数。
    • 解集不能包含重复的组合。

    代码:

     	private List<List<Integer>> resList;
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
    
            if (candidates == null || candidates.length == 0){
                return new ArrayList<>();
            }
    
            resList = new ArrayList<>();
    
            findCombinationByDFS(candidates,target,new ArrayList<>(),0);
            return resList;
        }
    
        private void findCombinationByDFS(int[] candidates, int target,List<Integer> list,int index){
    
            if (target == 0){
    
                resList.add(new ArrayList<>(list));
                return;
            }
    
            for (int i = index; i < candidates.length; i++) {
    
                if (candidates[i] <= target){
                    list.add(candidates[i]);
                    findCombinationByDFS(candidates,target-candidates[i],list,i);
                    list.remove(list.size() - 1);
                }
            }
        }
    

    40.含有相同元素的组合求和

    给定一个数组candidates和一个目标数target ,找出candidates中所有可以使数字和为target的组合。

    candidates中的每个数字在每个组合中只能使用一次。candidates中可能包含重复元素。

    说明:

    • 所有数字(包括目标数)都是正整数。
    • 解集不能包含重复的组合。
    private List<List<Integer>> resList;
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    
        if (candidates == null || candidates.length == 0){
            return new ArrayList<>();
        }
    	// 先排序
        Arrays.sort(candidates);
        int n = candidates.length;
        resList = new ArrayList<>();
        boolean[] visited = new boolean[n];
        findCombinationByDFS(candidates,target,0,new ArrayList<>(),visited);
    
        return resList;
    }
    
    private void findCombinationByDFS(int[] candidates,int target,int index,List<Integer> list,boolean[] visited){
    
        if (target == 0){
            resList.add(new ArrayList<>(list));
            return;
        }
    
        for (int i = index; i < candidates.length; i++) {
            // 避免重复的元素产生重复的组合
            if (i != 0 && candidates[i-1] == candidates[i] && !visited[i-1]){
                continue;
            }
    
            if (candidates[i] <= target){
                visited[i] = true;
                list.add(candidates[i]);
                findCombinationByDFS(candidates,target-candidates[i],i+1,list,visited);
                visited[i] = false;
                list.remove(list.size() - 1);
            }
        }
    }
    

    216.组合总和 III

    找出所有相加之和为nk个数的组合。组合中只允许含有1 - 9的正整数,并且每种组合中不存在重复的数字。

    说明:

    • 所有数字都是正整数。
    • 解集不能包含重复的组合。

    解析:

    ​ 组合中不允许重复的数字出现,所以每种数字在一个组合中最多出现一次。

    代码:

    private List<List<Integer>> resList;
    public List<List<Integer>> combinationSum3(int k, int n) {
    
        if (k == 0 || n == 0){
            return new ArrayList<>();
        }
    
        resList = new ArrayList<>();
    
        findByDFS(k,n,new ArrayList<>(),1);
        return resList;
    }
    
    private void findByDFS(int k,int n,List<Integer> list,int index){
    
        if (k == 0){
    
            if (n == 0){
                resList.add(new ArrayList<>(list));
            }
            return;
        }
    
        for (int i = index; i <= 9; i++) {
    
            list.add(i);
            findByDFS(k - 1,n - i,list,i + 1);
            list.remove(list.size() - 1);
        }
    }
    

    78.子集

    给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

    解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

    解析:

    这个题其实就是对第77题的一个小扩展,不再是只求某k个数的组合情况,而是求n个数的所有组成0..n个数的组合情况。

    	private List<List<Integer>> resList;
        public List<List<Integer>> subsets(int[] nums) {
    
            if (nums == null || nums.length == 0){
    
                return new ArrayList<>(new ArrayList<>());
            }
    
            resList = new ArrayList<>();
            // 按照子集合的大小依次寻找所有子集
            for (int i = 0; i <= nums.length; i++) {
                findSubSets(nums,new ArrayList<>(),i,0);
            }
    
            return resList;
        }
    
        private void findSubSets(int[] nums,List<Integer> list,int size,int index){
    
            if (list.size() == size){
                resList.add(new ArrayList<>(list));
                return;
            }
    
            for (int i = index; i < nums.length; i++) {
    
                list.add(nums[i]);
                findSubSets(nums,list,size,i + 1);
                list.remove(list.size() - 1);
            }
    
        }
    

    90.含有相同元素求子集

    给你一个整数数组nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。

    解集不能包含重复的子集。返回的解集中,子集可以按任意顺序排列。

      private List<List<Integer>> resList;
        public List<List<Integer>> subsetsWithDup(int[] nums) {
    
            if (nums == null || nums.length == 0){
                return new ArrayList<>(new ArrayList<>());
            }
    
            resList = new ArrayList<>();
            Arrays.sort(nums);
            boolean[] visited = new boolean[nums.length];
    
            for (int i = 0; i <= nums.length; i++) {
    
                findSubsetByDFS(nums,new ArrayList<>(),i,0,visited);
            }
    
            return resList;
        }
    
        private void findSubsetByDFS(int[] nums,List<Integer> list,int size,int index,boolean[] visited){
    
            if (size == list.size()){
    
                resList.add(new ArrayList<>(list));
                return;
            }
    
            for (int i = index; i < nums.length; i++) {
    
                   if (i != 0 && nums[i-1] == nums[i] && !visited[i-1]){
                       continue;
                   }
    
                   list.add(nums[i]);
                   visited[i] = true;
                   findSubsetByDFS(nums,list,size,i+1,visited);
                   visited[i] = false;
                   list.remove(list.size()-1);
            }
        }
    

    131.分割字符串

    给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

    回文串 是正着读和反着读都一样的字符串。

     private List<List<String>> resList;
        public List<List<String>> partition(String s) {
    
            if (s == null || s.length() == 0){
                return new ArrayList<>();
            }
    
            resList = new ArrayList<>();
    
            findSubStr(s,new ArrayList<>());
            return resList;
        }
    
        private void findSubStr(String s,List<String> list){
    
            if (s.length() == 0){
    
                resList.add(new ArrayList<>(list));
                return;
            }
    
            for (int i = 0; i < s.length(); i++) {
    
                if (isPalindrome(s,0,i)){
    
                    list.add(s.substring(0,i + 1));
                    findSubStr(s.substring(i + 1),list);
                    list.remove(list.size() - 1);
                }
            }
        }
    
        private boolean isPalindrome(String str,int left,int right){
    
            while (left < right){
    
                if (str.charAt(left++) != str.charAt(right--)){
                    return false;
                }
            }
            return true;
        }
    
  • 相关阅读:
    转:IOCP在网络应用中常见错误分析
    Ext.Button的禁用
    Excel连接字符串
    从表单为实体对象赋值
    根据指定类型创建数组
    Ext.GridPanel数据显示不正确
    vue 记事本
    杂谈(一)
    推荐《程序设计的 Top 10 做与不做》和《关于编程,鲜为人知的真相》
    (转)黄鸣博客:警惕29岁现象
  • 原文地址:https://www.cnblogs.com/yxym2016/p/14754629.html
Copyright © 2011-2022 走看看