zoukankan      html  css  js  c++  java
  • 算法图解——组合求和( Combination Sum)

     组合求和( Combination Sum)

    1. 题目描述

    Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.It is guaranteed that the number of unique combinations that sum up to target is less than 150 combinations for the given input.

    翻译过来就是:【还是建议大家先看英文的自己理解一下再看翻译】

    给定一个无重复整数数组candidates 和一个目标整数 target,返回一个唯一的候选组合的列表,其中所选列表中数字之和与目标数相等。返回的列表可以任意顺序。

    同一个数可从候选人中无限次选出。如果所选数字中至少一个的频率不同,则两个组合是唯一的。

    对于给定的输入,保证总计到目标的唯一组合数少于150个组合。


    2. 示例

    示例1:

    Input: candidates = [2,3,6,7], target = 7
    Output: [[2,2,3],[7]]
    Explanation:
    2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
    7 is a candidate, and 7 = 7.
    These are the only two combinations.

    示例2:

    Input: candidates = [2,3,5], target = 8
    Output: [[2,2,2,2],[2,3,3],[3,5]]

    示例3:

    Input: candidates = [2], target = 1
    Output: []

    示例4:

    Input: candidates = [1], target = 1
    Output: [[1]]

    示例5:

    Input: candidates = [1], target = 2
    Output: [[1,1]]

    3. 要求

    • 1 <= candidates.length <= 30
    • 1 <= candidates[i] <= 200
    • All elements of candidates are distinct【数组元素都是不一样的】.
    • 1 <= target <= 500

    4. 解题思路 

    此题其实类似于背包问题,可以利用贪心的思想。先排序,然后从第一个元素遍历,当把元素 sum[i] 加入到列表 arr 中后(求和列表),剩下的问题其实就是一个子问题——求数组num中和为 target-sum[i] 的子问题。但是 sum[i] 也可能不是求和数组 arr 中的元素,即有了sum[i] 后就不可能组合成target之和。故在递归后,还得需要把该元素给回退掉。

    即:

    arr.add(nums[i]);  //添加元素
    search(res,arr,nums,target-nums[i],i);  //递归
    arr.remove(arr.size()-1);//如果不满足的话,还可以退回。

    5. 实现:

     全文代码实现:

    class Solution {
        public List<List<Integer>> combinationSum(int[] nums, int target) {
            ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
            Arrays.sort(nums);//背包问题
            
            search(res,new ArrayList<Integer>(),nums,target,0);
            return res;
        }
        private void search(ArrayList<List<Integer>> res,ArrayList<Integer> arr,int[] nums,int target,int index){
            //待求和为0时
            if(target==0){
                res.add(new ArrayList<Integer>(arr));
                return;
            }
            //待求和<0时返回空。因为1 <= candidates[i] <= 200,且1 <= target <= 500
            if(target<0)  return;
            
            for(int i=index;i<nums.length;i++){
                if(target-nums[i]>=0){
                    arr.add(nums[i]);
                    search(res,arr,nums,target-nums[i],i);  //递归,注意这里是i 不是i++;
                    arr.remove(arr.size()-1);//如果不满足的话,还可以退回。
                }else
                    break;
            }
        }
    }

    6. 拓展:

    题目上说的是求和数组 arr 中的元素可以重复,如示例1,2:

    Input: candidates = [2,3,6,7], target = 7
    Output: [[2,2,3],[7]]
    Input: candidates = [2,3,5], target = 8
    Output: [[2,2,2,2],[2,3,3],[3,5]]

    那么,如果该要求改为不可以重复,该如何解呢?

    Input: candidates = [2,3,6,7], target = 7
    Output: [[7]]
    
    Input: candidates
    = [2,3,5], target = 8 Output: [[3,5]]

    其实,我们只需要在添加元素 nums[i] 到arr 中后,再把原数组nums 中对应的元素给去掉就行,然后形成子问题,再之后再恢复过来即可。

    参考致谢:

    1、LeetCode Top 100 高频算法题39. Combination Sum

    Over......

  • 相关阅读:
    团队作业(二):项目选题
    今天准备正式开博了!专注于Silverlight!
    ORA01033:ORACLE initialization or shutdown in progress 错误的解决办法
    寻找正在应用和准备学习XNAor3D技术的志同道合的伙伴,大家能够互帮互助,共同探讨,最好能够组成较固定的小团队!
    TNS: could not resolve the connect identifier specified
    今天连接字符串出现了“ORA01008: 并非所有变量都已绑定”错误
    选择HttpHandler还是HttpModule?
    jQuerymenuaim.js
    MVP解读
    揭秘Amazon反应速度超快的下拉菜单
  • 原文地址:https://www.cnblogs.com/gjmhome/p/14400377.html
Copyright © 2011-2022 走看看