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日

相关推荐

  • leetcode733-图像渲染

    原题 有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间。 给你一个坐标 (sr, sc) 表示图像渲染开始的像素值(行 ,列)和一…

    2019年12月13日
    0100
  • leetcode67-二进制求和

    原题 给定两个二进制字符串,返回他们的和(用二进制表示)。 输入为非空字符串且只包含数字 1 和 0。 示例 1: 输入: a = “11”, b = “1” 输出: “100” …

    算法 2019年11月15日
    0100
  • 海量数据-两种方法解决top k问题

    假如提供一百万个数据(甚至更大)的无序数组,如何从中获取最大的k个元素? 最容易想到的是先降序排序然后获取前k个元素,那假设我们用最常用的O(nlogn)级别的排序算法,要获取to…

    2020年4月4日
    0220
  • 程序员面试金典17.16-按摩师

    原题(来源Leetcode) 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,…

    算法 2020年3月24日
    0930
  • leetcode341-扁平化嵌套列表迭代器

    原题 给定一个嵌套的整型列表。设计一个迭代器,使其能够遍历这个整型列表中的所有整数。 列表中的项或者为一个整数,或者是另一个列表。 示例1: 输入: [[1,1],2,[1,1]]…

    算法 2020年1月27日
    050
  • 蓝桥杯试题-大小写转换

    原题 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述   输入一个字符串,将大写字符变成小写、小写变成大写,然后输出 输入格式 acbAB 输出格式 ACBab …

    算法 2020年2月29日
    060
  • leetcode636-函数的独占时间

    原题 给出一个非抢占单线程CPU的 n 个函数运行日志,找到函数的独占时间。 每个函数都有一个唯一的 Id,从 0 到 n-1,函数可能会递归调用或者被其他函数调用。 日志是具有以…

    算法 2020年2月2日
    0190
  • leetcode12-整数转罗马数字

    原题 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2…

    算法 2020年2月29日
    070
  • leetcode215-数组中的第K个最大元素

    原题 在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 示例1: 输入: [3,2,1,5,6,4] 和…

    算法 2020年2月10日
    0140
  • leetcode142-环形链表II

    原题 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始…

    2019年12月14日
    0440

发表回复

登录后才能评论