leetcode39-组合总和

原题

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

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

说明:

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

示例 1:

输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
  [7],
  [2,2,3]
]

示例 2:

输入: candidates = [2,3,5], target = 8,
所求解集为:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

解法

本题解同步发于leetcode题解:Java DFS,让你知道组合怎么去重&剪枝&回溯到底是什么

思想

该题难点在于组合的去重,如果直接不加条件的dfs很容易找到相同的组合,例如示例一可以找出[2,2,3][2,3,2][3,2,2],它们实质上是同一个组合。如果要进行去重,可以考虑给组合添加一个限制条件,例如我们要求,找到的组合中前面的数必须大于等于后面的数。

那么为了只找到满足条件的组合,可以先将candidates数组从小到大排序,每次dfs选取一个元素之后,我们就不再选取比它大的元素(即后面只在下标小于等于它的元素中查找)。这样就可以做到查找到的组合满足前面的数总是大于等于后面的数。

这样的dfs查找,如果画出树状图的话,会看到这个搜索树因为某些部分条件不满足,于是不再向下查找,称为“剪枝”。

leetcode39-组合总和

leetcode39-组合总和

那么其他题解说的“回溯算法”是什么呢,其实用递归实现的DFS就必然会经过回溯,当条件不满足时,递归函数需要返回到上一层节点,继续查找,称为“回溯”。

代码

class Solution {
    List<List<Integer>> ans;
    int[] candidates;
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        ans = new ArrayList<>();
        //先对candidates从小到大排序
        Arrays.sort(candidates);
        this.candidates = candidates;
        List<Integer> list = new ArrayList<>();
        dfs(list,target,candidates.length-1);
        return ans;
    }

    //maxIndex表示允许在candidates搜索到的最大下标
    public void dfs(List<Integer> list,int target,int maxIndex){
        for(int i = 0;i<=maxIndex;i++){
            if(candidates[i]<=target){
                List<Integer> copyList = new ArrayList<>(list);
                copyList.add(candidates[i]);
                if(candidates[i]==target) {
                    ans.add(copyList);
                    return;
                }
                //当选取下标为i的节点后,下一步只允许在下标小于等于i的元素中查找
                dfs(copyList,target-candidates[i],i);
            }
        }
    }
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/leetcode39-%e7%bb%84%e5%90%88%e6%80%bb%e5%92%8c/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年4月30日
下一篇 2020年5月1日

相关推荐

  • leetcode260-只出现一次的数字III

    原题 给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。 示例: 输入: [1,2,1,3,2,5] 输出: [3,5…

    算法 2020年4月28日
    0150
  • leetcode124-二叉树中的最大路径和

    原题 给定一个非空二叉树,返回其最大路径和。 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。 示例 1: 输入: [1…

    算法 2020年4月26日
    0170
  • leetcode55-跳跃游戏

    原题 原题 给定一个非负整数数组,你最初位于数组的第一个位置。 数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个位置。 示例1: 输入: [2,3,1…

    算法 2020年2月9日
    080
  • leetcode572-另一个树的子树

    原题 给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树…

    算法 2020年5月8日
    0380
  • leetcode1028-从先序遍历还原二叉树

    原题 我们从二叉树的根节点 root 开始进行深度优先搜索。 在遍历中的每个节点处,我们输出 D 条短划线(其中 D 是该节点的深度),然后输出该节点的值。(如果节点的深度为 D,…

    2020年6月18日
    02410
  • leetcode49-字母异位词分组

    原题 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。 示例: 输入: ["eat", "tea", "tan", "ate", "nat",…

    算法 2019年12月25日
    0110
  • leetcode373-查找和最小的K对数字

    原题 给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k。 定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2。 找到和最…

    算法 2020年2月13日
    0160
  • leetcode110-平衡二叉树

    原题 给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 示例 1:  给定二叉树 […

    算法 2020年1月17日
    0170
  • leetcode387-字符串中的第一个唯一字符

    原题 给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。 案例: s = "leetcode" 返回 0. s = "loveleetcode"…

    算法 2019年12月22日
    0130
  • leetcode6-Z 字形变换

    原题 https://leetcode.cn/problems/zigzag-conversion/description 解法 遍历每行,按照对称规律都能找到下一个要遍历的下标是…

    算法 2024年3月23日
    0120

发表回复

登录后才能评论