leetcode 39. Combination Sum

一 题目

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

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

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [2,3,6,7], 
target = 7,
A solution set is:
[
  [7],
  [2,2,3]
]

Example 2:

Input: candidates = [2,3,5], 
target = 8,
A solution set is:
[
  [2,2,2,2],
  [2,3,3],
  [3,5]
]

Accepted 394,084 Submissions 777,329

二 分析

medium 级别难度,这是一道经典题目。求数组里面能组合成target的数字所有组合。它允许结果出现重复数字。

我做题还处于入门摸索阶段,但是如果做完一贷题目,后面提示你有 类似这种:Combination Sum IICombinationsCombination Sum IIIFactor CombinationsCombination Sum IV。就是说明它有体系,成套路的衍生出相关的题目。值得去做。

回溯法(递归)

  这种问题的思路,跟之前做的数独题优点类似,尝试去匹配,如果满足条件,就下一步,不满足就回退重新选择。

因此题目的关键就转变成递归函数的实现。图片来自花花酱大神,主要体现了DFS就是深度优先的思路。https://zxi.mytechroad.com/blog/searching/leetcode-39-combination-sum/  

思路:

1.先排序 ,防止乱序导致重复搜索。

2. 递归参数:增加index(根据题目要求必须遍历所有可能性才能求解。为了避免重复遍历,我们搜索的时候只搜索当前或之后的数,而不再搜索前面的数),临时结果list, 最终结果res,还有临时sum。

  如果  临时sum》target:  不满足,返回。

   如果 临时sum == target,匹配,加入结果。

如果  临时sum<target, 从之前的位置开始,尝试加入,递归,不匹配则移除。

public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] candidates ={2,3,6,7};
		List res = combinationSum(candidates,7);
		System.out.println(res);
	}

	public static List<List<Integer>> combinationSum(int[] candidates, int target) {
		
		List<List<Integer>> res = new ArrayList();
		List<Integer> tlist = new ArrayList();
		//先排序
		Arrays.sort(candidates);
	     //拆分rule
		combin( candidates,  target,0,tlist,res,0);				
		return res;        
    }
	
	private static void combin(int[] arrays,int target,int index,List<Integer> temp,List<List<Integer>> result,int tempsum){
		
		//超范围,不匹配
		if(tempsum> target){
			return;
		}//匹配,加入结果集
		else if(target ==tempsum){
			result.add(new ArrayList( temp));
		}else{
			//<target,继续搜索
			for(int i=index;i<arrays.length;i++ ){
				if(arrays[i]>target){
					break;
				}
				//先放入
				temp.add(arrays[i]);
				//尝试匹配
				combin(arrays,target, i, temp,result,tempsum+arrays[i]);
				//在取出:最后加入的
				temp.remove(temp.size()-1);
			}			
		}		
	}

Runtime: 7 ms, faster than 19.80% of Java online submissions forCombination Sum.

Memory Usage: 37.9 MB, less than 100.00% of Java online submissions for Combination Sum.

时间复杂度O(N!)

如归按照大神的写法,如下所示,直接使用target-arrays[i],匹配的时候判断target==0.就避免了多传临时结果,求和。速度更快了。

  private  void combin(int[] arrays,int target,int index,List<Integer> temp,List<List<Integer>> result){
		
		//超范围,不匹配
		if( target<0){
			return;
		}//匹配,加入结果集
		else if(target ==0){
			result.add(new ArrayList( temp));
		}else{
			//<target,继续搜索
			for(int i=index;i<arrays.length;i++ ){
				if(arrays[i]>target){
					break;
				}
				//先放入
				temp.add(arrays[i]);
				//尝试匹配
				combin(arrays,target-arrays[i], i, temp,result);
				//在取出:最后加入的
				temp.remove(temp.size()-1);
			}			
		}		
	}

Runtime: 2 ms, faster than 99.82% of Java online submissions forCombination Sum.

Memory Usage: 37.3 MB, less than 100.00% of Java online submissions for Combination Sum.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值