leetcode-39/40 Combination Sum / II

一、leetcode39 Combination Sum

问题描述:

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

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

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
  • 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] 

 

问题分析:

一个很明显的DFS(深度优先遍历)的问题,注意每个节点可以重复利用即可。

 

代码:

public class Solution39 {
    /*** 简单的DFS算法***/
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
       List<List<Integer>> result = new ArrayList<>();
       if(candidates == null || candidates.length == 0)
           return result;
 
        //先对数组进行排序
        Arrays.sort(candidates);
        //每次遍历暂存节点数组
        List<Integer> curr = new ArrayList<Integer>();
 
        DFS_Search(candidates, target, 0 , curr, result);
        return result;
    }
 
 
    /***
     * @paramcandidates-- 源数据数组
     * @paramtarget    -- 目标值
     * @paramindex     -- 该循环数组起始位置
     * @paramcurr      -- 暂存该次遍历中的所有节点
     * @paramresult    -- 结果数组
     ***/
    private void DFS_Search(int[] candidates, int target, int index, List<Integer> curr, List<List<Integer>> result) {
        //递归返回标志
        if(target== 0){
           List<Integer> temp = new ArrayList<Integer>(curr);
           result.add(temp);
           return;
        } else{
 
           for (int i = index; i < candidates.length; i++){
                if(candidates[i] > target)
                    return;
                else {
                    curr.add(candidates[i]);
                    // 因为可以重复使用某个值,所以这里依然index使用i
                    DFS_Search(candidates, target- candidates[i], i, curr, result);
                    curr.remove(curr.size() - 1);
               }
           }
        }
    }
 
}

二、leetcode-40 Combination Sum II

问题分析:

    与前面Combination Sum问题相比,其区别在于不能再重复利用同一个值;而且数组中可能出现值相同的元素。

    这里寻找匹配值同样还是应该用DFS算法,但与前面不同的是要注意考虑重复值的问题;

    消除重复值的策略是:如果前面路径中使用了某一元素,则下一相同值元素才可以使用(还要注意考虑如多个元素值相同的情况)。

    下面代码在Combination Sum基础上添加了一个用以记录上一个元素是否在路径中被使用的变量flag;在消除重复值时,仅需要判别flag即可。

 

代码:

public class Solution40 {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
	   List<List<Integer>> result = new ArrayList<>();

       if(candidates == null || candidates.length == 0)
           return result;
       // 先对数组进行排序
       Arrays.sort(candidates);

       List<Integer> curr = new ArrayList<>();
       DFS_Search2(candidates, target, 0 , curr, result, false);
       return result;
    }

    
    /***
     * @param candidates-- 源数据数组
     * @param target    -- 目标值
     * @param index     -- 该循环数组起始位置
     * @param curr      -- 暂存该次遍历中的所有节点
     * @param result    -- 结果数组
     * @param flags     -- 用以标志前一个元素是否被使用
     * 
     ***/
    private void DFS_Search2(int[] candidates, int target, int index, List<Integer> curr, List<List<Integer>> result, boolean flags){
        if(target == 0) { 
            result.add(new ArrayList(curr));
            return;
        } else {
            for(int i = index; i < candidates.length; i++) {
                // 处理有重复值情况
                if((i >= 1) && candidates[i] == candidates[i - 1]) {
                    if(!flags){
                        continue;
                    }    
                }

                if(candidates[i] > target) 
                    return;

                curr.add(candidates[i]);
                flags = true;
                DFS_Search2(candidates, target - candidates[i], i + 1, curr, result, true);
                curr.remove(curr.size() - 1);
                flags = false;
            }
        }
    }
    
   public static void main(String[] args){
    	
    	int[] data = {2, 2, 2};
    	int target = 4;
    	List<List<Integer>> results = new ArrayList<>();
    	results = new Solution40().combinationSum2(data, target);
    	System.out.println(results);
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值