LeetCode刷题:39. Combination Sum

LeetCode刷题:39. Combination Sum

原题链接:https://leetcode.com/problems/combination-sum/description/

Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

The same repeated number may be chosen from C unlimited number of times.

Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7] and target 7,
A solution set is:
[
[7],
[2, 2, 3]
]

这个题目的意思是给定一个集合,集合中的元素不重复,并且包含一个目标值(即目标值也是集合中的一个元素),从集合中找出所有不重复的元素的组合,使得这些元素之和等于目标值。注意,结果集合中的元素可以重复出现。
例如:给定集合 [2, 3, 6, 7] 和目标值7,符合上述题目要求的结果集合为:
[
[7],
[2, 2, 3]
]

问题分析:可以采用DFS搜索算法求解。

算法设计

package com.bean.algorithmbasic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class CombinationSum {
    /*
     * 可能的答案存在多个集合的情况,所以combinationSum方法返回值为一个List,
     * 而list中的每一个元素均为一个List集合,其中每一个元素的类型均为Integer
     * 
     * 输入参数:目标数组和目标值
     * 
     * 
     * */
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> ans = new ArrayList<>();
        //对目标数组排序
        Arrays.sort(candidates);
        /*
         * 调动dfs算法
         * 输入参数的含义:ans为答案List集合
         * new ArrayList<Integer>() 为存放临时结果的ArrayList集合
         * candidates为候选值
         * target为目标值
         * 0 为开始搜索的位置下标
         * */
        dfs(ans, new ArrayList<Integer>(), candidates, target, 0);
        return ans;
    }

    /*
     * dfs算法设计
     * 
     * */
    private void dfs(List<List<Integer>> ans, List<Integer> list, int[] cand, int remain, int from) {
        //如果没有剩余的元素了,则结束搜索,返回。(搜索结束条件)
        if (remain < 0) {
            return;
        }
        //如果搜索到最后将临时结果加入答案中,并返回。结束搜索
        if (remain == 0) {
            ans.add(new ArrayList<Integer>(list));
            return;
        }
        //从开始位置(from参数),到cand数组的最后一个元素位置,进行搜索
        for (int i = from; i < cand.length; ++i) { 
            // cand[] sorted; from is the starting point of picking elements at this level
            list.add(cand[i]);
            //remain-cand[i]的含义是当目标值减去候选数组的元素之后,对剩余的数组元素再进行搜索
            dfs(ans, list, cand, remain - cand[i], i);
            list.remove(list.size() - 1);
        }
    }

    public static void main(String args[]) {

        int[] array= {2, 3, 6, 7};
        int target=7;

        CombinationSum cs=new CombinationSum();
        List<List<Integer>> list=cs.combinationSum(array, target);
        Iterator<List<Integer>> itx=list.iterator();
        while(itx.hasNext()) {
            List<Integer> lt=itx.next();
            System.out.println(lt);
        }
    }
}

运行结果:

[2, 2, 3]
[7]

另外一种求解方法
递归思想求解
首先把=target的数保存到list,将

package com.bean.algorithmbasic;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class CombinationSum2 {

    public List<List<Integer>> combinationSum(int[] array, int target) {  
        List<List<Integer>> list = new ArrayList<List<Integer>>();  
        Arrays.sort(array);//数组排序  
        //各种特殊情况  
        if(array.length == 0 || array[0] > target)  
            return list;  

        int len = 0;  
        boolean isAdd = false;//控制与target相等的数只添加一次  
        for(int i = 0; i< array.length;i++){  
            if(array[i] == target){  
                if(!isAdd){//如果未添加  
                    List<Integer> al = new ArrayList<Integer>();  
                    al.add(target);  
                    list.add(al);  
                    isAdd = true;//标记已添加  
                }  
            }else if(array[i] < target){//只要比target小的值,大的值肯定不满足,排除  
                array[len++] = array[i];//新数组  
            }  
        }  
        //只存在array[0] < target 或 array[0] > target  
        if(array[0] > target)//肯定已没有符合要求的组合  
            return list;  
        //array[0] < target  

        for(int i = 0; i < len; i++){//循环搜索符合要求的数字组合  
            int[] b = Arrays.copyOfRange(array, i, len);//不含>=t数据的新数组  
            if(array[i] > target)//如果array[i],肯定以后的数据已不符合,返回  
                break;  
            //相等于已经有了一个值array[0]了      
            List<List<Integer>> newList = new ArrayList<List<Integer>>();  
            //递归求解
            newList = combinationSum(b,target-array[i]);  
            if(newList.size() > 0){//里面有符合要求的数据  
                for(int j = 0; j < newList.size();j++){  
                    newList.get(j).add(array[i]);//新返回的各个值添加array[0]  
                    Collections.sort(newList.get(j));//排序  
                    list.add(newList.get(j));//最终添加  
                }  
            }  
        }  
        return list;  
    }  


    public static void main(String args[]) {

        int[] array = { 2, 3, 6, 7 };
        int target = 7;

        CombinationSum2 cs = new CombinationSum2();
        List<List<Integer>> list = cs.combinationSum(array, target);
        Iterator<List<Integer>> itx = list.iterator();
        while (itx.hasNext()) {
            List<Integer> lt = itx.next();
            System.out.println(lt);
        }
    }
}

(完)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值