zoukankan      html  css  js  c++  java
  • 大佬总结的leetcode回溯算法题目

    39.组合总和 √

    40. 组合总和 II

    46. 全排列

    47. 全排列 II

    78. 子集√

    90. 子集 II

    78题 子集

    给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

    说明:解集不能包含重复的子集。

    作者:powcai

    链接:https://leetcode-cn.com/problems/subsets/solution/hui-su-suan-fa-by-powcai-5/
    来源:力扣(LeetCode)

    回溯法:

    class Solution {
        public List<List<Integer>> subsets(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            backtrack(0, nums, res, new ArrayList<Integer>());
            return res;
    
        }
    
        private void backtrack(int i, int[] nums, List<List<Integer>> res, ArrayList<Integer> tmp) {
            res.add(new ArrayList<>(tmp));!!!!!
            for (int j = i; j < nums.length; j++) {
                tmp.add(nums[j]);
                backtrack(j + 1, nums, res, tmp);
                tmp.remove(tmp.size() - 1);
            }
        }
    }

    此题可以用位掩码方法:

    作者:liweiwei1419
    链接:https://leetcode-cn.com/problems/subsets/solution/hui-su-python-dai-ma-by-liweiwei1419/
    来源:力扣(LeetCode)

    import java.util.ArrayList;
    import java.util.List;
    
    public class Solution5 {
    
        public List<List<Integer>> subsets(int[] nums) {
            int size = nums.length;
            int n = 1 << size;
            List<List<Integer>> res = new ArrayList<>();
    
            for (int i = 0; i < n; i++) {
                List<Integer> cur = new ArrayList<>();
                for (int j = 0; j < size; j++) {
                    if (((i >> j) & 1) == 1) {
                        cur.add(nums[j]);
                    }
                }
                res.add(cur);
            }
            return res;
        }
    
        public static void main(String[] args) {
            int[] nums = {1, 2, 3};
            Solution5 solution5 = new Solution5();
            List<List<Integer>> subsets = solution5.subsets(nums);
            System.out.println(subsets);
        }
    }

    39题 数组总和

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

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

    回溯法:

    作者:liweiwei1419
    链接:https://leetcode-cn.com/problems/combination-sum/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-2/
    来源:力扣(LeetCode)

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Stack;
    
    public class Solution {
    
        private List<List<Integer>> res = new ArrayList<>();
        private int[] candidates;
        private int len;
    
        private void findCombinationSum(int residue, int start, Stack<Integer> pre) {
            if (residue == 0) {
                // Java 中可变对象是引用传递,因此需要将当前 path 里的值拷贝出来
                res.add(new ArrayList<>(pre));
                return;
            }
            // 优化添加的代码2:在循环的时候做判断,尽量避免系统栈的深度
            // residue - candidates[i] 表示下一轮的剩余,如果下一轮的剩余都小于 0 ,就没有必要进行后面的循环了
            // 这一点基于原始数组是排序数组的前提,因为如果计算后面的剩余,只会越来越小
            for (int i = start; i < len && residue - candidates[i] >= 0; i++) {
                pre.add(candidates[i]);
                // 【关键】因为元素可以重复使用,这里递归传递下去的是 i 而不是 i + 1
                findCombinationSum(residue - candidates[i], i, pre);
                pre.pop();
            }
        }
    
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            int len = candidates.length;
            if (len == 0) {
                return res;
            }
            // 优化添加的代码1:先对数组排序,可以提前终止判断
            Arrays.sort(candidates);
            this.len = len;
            this.candidates = candidates;
            findCombinationSum(target, 0, new Stack<>());
            return res;
        }
    
        public static void main(String[] args) {
            int[] candidates = {2, 3, 6, 7};
            int target = 7;
            Solution solution = new Solution();
            List<List<Integer>> combinationSum = solution.combinationSum(candidates, target);
            System.out.println(combinationSum);
        }
    }

    这里有一个更快的

    作者:powcai
    链接:https://leetcode-cn.com/problems/combination-sum/solution/xue-yi-tao-zou-tian-xia-hui-su-suan-fa-by-powcai/
    来源:力扣(LeetCode)

    class Solution {
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            List<List<Integer>> res = new ArrayList<>();
            Arrays.sort(candidates);
            //System.out.println(candidates);
            backtrack(candidates, target, res, 0, new ArrayList<Integer>());
            return res;
        }
    
        private void backtrack(int[] candidates, int target, List<List<Integer>> res, int i, ArrayList<Integer> tmp_list) {
            if (target < 0) return;
            if (target == 0) {
                res.add(new ArrayList<>(tmp_list));
                return;
            }
            for (int start = i; start < candidates.length; start++) {
                if (target < candidates[start]) break;
                //System.out.println(start);
                tmp_list.add(candidates[start]);
                //System.out.println(tmp_list);
                backtrack(candidates, target - candidates[start], res, start, tmp_list);
                tmp_list.remove(tmp_list.size() - 1);
            }
        }
    }

    40题 组合总数||

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

    说明:所有数字(包括目标数)都是正整数。解集不能包含重复的组合。 

    作者:powcai
    链接:https://leetcode-cn.com/problems/combination-sum-ii/solution/hui-su-xi-lie-by-powcai/
    来源:力扣(LeetCode)

    class Solution {
       public List<List<Integer>> combinationSum2(int[] candidates, int target) {
            Arrays.sort(candidates);
            List<List<Integer>> res = new ArrayList<>();
            backtrack(res, candidates, target, 0, 0, new ArrayList<Integer>());
            return res;
    
        }
    
        private void backtrack(List<List<Integer>> res, int[] candidates, int target, int i, int tmp_sum, ArrayList<Integer> tmp_list) {
            if (tmp_sum == target) {
                res.add(new ArrayList<>(tmp_list));
                return;
            }
            for (int start = i; start < candidates.length; start++) {
                if (tmp_sum + candidates[start] > target) break;
                if (start > i && candidates[start] == candidates[start - 1]) continue;
                tmp_list.add(candidates[start]);
                backtrack(res, candidates, target, start + 1, tmp_sum + candidates[start], tmp_list);
                tmp_list.remove(tmp_list.size() - 1);
            }
        }
    }

     46. 全排列

    给定一个没有重复数字的序列,返回其所有可能的全排列。

    作者:powcai
    链接:https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-by-powcai-2/
    来源:力扣(LeetCode)

    class Solution {
        public List<List<Integer>> permute(int[] nums) {
    
            List<List<Integer>> res = new ArrayList<>();
            int[] visited = new int[nums.length];
            backtrack(res, nums, new ArrayList<Integer>(), visited);
            return res;
    
        }
    
        private void backtrack(List<List<Integer>> res, int[] nums, ArrayList<Integer> tmp, int[] visited) {
            if (tmp.size() == nums.length) {
                res.add(new ArrayList<>(tmp));
                return;
            }
            for (int i = 0; i < nums.length; i++) {
                if (visited[i] == 1) continue;
                visited[i] = 1;
                tmp.add(nums[i]);
                backtrack(res, nums, tmp, visited);
                visited[i] = 0;
                tmp.remove(tmp.size() - 1);
            }
        }
    }

    更快方法:

    class Solution {
        public List<List<Integer>> permute(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            if (nums == null || nums.length == 0) return res;
            List<Integer> list = new ArrayList<>();
            for (int num : nums) {
                list.add(num);
            }
            dfs(list, res, 0);
    
            return res;
        }
    
        private void dfs(List<Integer> nums, List<List<Integer>> res, int start) {
            if( start == nums.size()) {
                res.add(new ArrayList<>(nums));
            }
            else {
                for (int i = start; i < nums.size(); i++) {
                    Collections.swap(nums, i, start);
                    dfs(nums, res, start+1); //交换当前位置后,从下一个位置开始重新排列填充
                    Collections.swap(nums, i, start); //重新排列后再恢复
                }
            }
        }
    }
  • 相关阅读:
    openfl使用64位的ndk时,编译报错的问题!
    Haxe是何物?
    jsp中如何判断el表达式中的BigDecimal==0
    如何在springmvc的请求过程中获得地址栏的请求
    【原创】【滑块验证码】
    【原创】【aes加密】
    【原创】【qrcodejs2】生成二维码
    【原创】【ueditor】监听内容
    【原创】【ueditor】内容过多时 菜单控件遮挡页面
    js杂谈
  • 原文地址:https://www.cnblogs.com/doyi111/p/11807093.html
Copyright © 2011-2022 走看看