zoukankan      html  css  js  c++  java
  • [array] leetcode

    leetcode - 39. Combination Sum - Medium

    descrition

    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]
    ]
    
    

    解析

    典型的回溯法求解。代码实现中给出了 3 中回溯的方式,都 accepted。微妙的区别应该是在递归的层数不同。对于 candidates[index] 只有两种情况,即:选择或不选择,值得注意的是如果选择的话可以多次重复选择。(可以使用状态转换图进行抽象更便于理解,重复选择实际上是在 index 状态有环,而不选择则是向 index + 1 状态的迁移)

    注意:

    • 调用函数前用了一个排序,主要是为了递归时剪枝做准备,数组是递增排序,如果太大则可以停止更深层的递归
    • 题目说了所有数都是 positive,这其实也可以作为剪枝的条件
    • 题目说数组中不存在 duplicate 元素,如果存在的话还需要跳过重复的元素。

    一般的,对于回溯问题,找好递归求解的子结构,记得结束点即出口的检查,避免无限循环。在递归过程中可以思考是否可以进行剪枝。

    code

    
    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    class Solution{
    public:
    	vector<vector<int> > combinationSum(vector<int>& candidates, int target){
    		vector<vector<int> > ans;
    		vector<int> vecCur;
    		sort(candidates.begin(), candidates.end());
    		
    		combinationSumBacktracking0(candidates, 0, target, vecCur, ans);
    		//combinationSumBacktracking1(candidates, 0, target, vecCur, ans);
    		//combinationSumBacktracking2(candidates, 0, target, vecCur, ans);
    		return ans;
    	}
    
    	// candidates in ascending
    	void combinationSumBacktracking0(vector<int>& candidates, int index, int target, 
    				        vector<int>& vecCur, vector<vector<int> >& ans){
    		if(target < 0)
    			return;
    		if(target == 0 && !vecCur.empty()){
    			ans.push_back(vecCur);
    			return;
    		}
    		// sub-problem, for each element in candidates[index,...,n-1]
    		// just have two condition: choose or not
    		for(int i=index; i<candidates.size(); i++){
    			if(candidates[i] > target) // Note: candidates must in ascending order
    				break;
    			// note: not i+1, because the same repeaded number may be chosen from candidates
    			vecCur.push_back(candidates[i]);
    			combinationSumBacktracking0(candidates, i, target - candidates[i], vecCur, ans);
    			vecCur.pop_back();
    		}
    	}
    
    	void combinationSumBacktracking1(vector<int>& candidates, int index, int target,
    								    vector<int>& vecCur, vector<vector<int> >& ans){
    		if(target < 0)
    			return;
    		if(target == 0){
    			if(!vecCur.empty())
    				ans.push_back(vecCur);
    			return;
    		}
    		if(index >= candidates.size())
    			return;
    
    		// choose candidates[index]
    		// Note: candidates[index] can be choose more than onece
    		vecCur.push_back(candidates[index]);
    		combinationSumBacktracking1(candidates, index, target - candidates[index], vecCur, ans);
    		vecCur.pop_back();
    
    		// dosen't choose candidates[index]
    		combinationSumBacktracking1(candidates, index+1, target, vecCur, ans);
    	}
    
    	void combinationSumBacktracking2(vector<int>& candidates, int index, int target,
    									 vector<int>& vecCur, vector<vector<int> >& ans){
    		if(target < 0)
    			return;
    		if(target == 0){
    			if(!vecCur.empty())
    				ans.push_back(vecCur);
    			return;
    		}
    		if(index >= candidates.size())
    			return;
    
    		// choose candidates[index] more than times
    		int i = 1;
    		for(; i*candidates[index] <= target; i++){
    			vecCur.push_back(candidates[index]);
    			combinationSumBacktracking2(candidates, index+1, target - i*candidates[index], vecCur, ans);
    		}
    		for(int j=i-1; j>=1; j--)
    			vecCur.pop_back();
    
    		// don't choose candidates[index]
    		combinationSumBacktracking2(candidates, index+1, target, vecCur, ans);
    	}
    };
    
    int main()
    {
    	return 0;
    }
    
  • 相关阅读:
    如何找出一个数组中第二大的数
    如何把一个整型数组中重复的数字去掉
    假设数组a有n个元素,元素取值范围是1~n,如何判定数组是否存在重复元素
    如何重新排列数组使得数组左边为奇数,右边为偶数,并使得空间复杂度为O(1),时间复杂度为O(n)
    给一个由n-1个整数组成的未排序的序列,其元素都是1~n中的不同的整数。如何在线性时间复杂度内寻找序列中缺失的整数
    已知大小分别为m、n的两个无序数组A、B和一个常数c,求满足A[i]+B[j]=c的所有A[i]和B[j]
    如何找出数组中符合条件的数对
    如何找出数组中出现奇数次的元素
    云服务器ECS挖矿木马病毒处理和解决方案
    Java下载https文件上传到阿里云oss服务器
  • 原文地址:https://www.cnblogs.com/fanling999/p/7846111.html
Copyright © 2011-2022 走看看