leetcode题解日练--2016.7.18

来源:互联网 发布:扫描二维码抽奖软件 编辑:程序博客网 时间:2024/05/30 04:33

日练三题,冰冻三尺非一日之寒。

今日题目:1、子集;2、组合加法;3、组合加法II 。

今日摘录:

世上只有一本书就是你,别的书,都是它的注释。
——顾城 《顾城哲思录》

78. Subsets | Difficulty: Medium

Given a set of distinct integers, nums, return all possible subsets.
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,3], a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]

题意:找出一个集合的所有子集。

思路:
1、找一个集合中的子集,一个n个元素的集合,它的子集个数有2的n次方种,好像联想到了什么,没错,2^n种可能性正好可以用n位2进制数来表示,而且每一位的意义都很好解释,就是集合中相对应的位置的元素有和没有两种情况。
这里如果要求子集是有顺序的,那么之前应该先进行一次排序操作,否则就无需做排序。看题目给的示例是从小到大的,那么我们就先对集合元素进行排序,然后再找子集。

class Solution {public:    vector<vector<int>> subsets(vector<int>& nums) {        sort(nums.begin(),nums.end());        int elem_nums = nums.size();        int sub_nums = pow(2,elem_nums);        vector<vector<int>> res(sub_nums,vector<int>());        for(int i=0;i<elem_nums;i++)        {            for(int j=0;j<sub_nums;j++)            {                //第j个子集的第i位是1                if((j>>i)&1)        res[j].push_back(nums[i]);            }        }        return res;    }};

结果:8ms

2、迭代去做,最开始res是[[]],遍历一次我们的集合,然后对于res的每一个元素,都对其加上遍历到的元素。这样第一次遍历之后1个元素变成2个元素,第二次遍历之后2个元素变成4个元素,第三次4个元素变成8个元素。正好是我们需要的,能这么想代码就已经不是问题了。

class Solution {public:    vector<vector<int>> subsets(vector<int>& nums) {        sort(nums.begin(),nums.end());        vector<vector<int>> res(1,vector<int>());        //遍历每个集合中的元素        for(int i=0;i<nums.size();i++)        {            //在每次遍历的时候确认一下之后的结果集合有多大            int size = res.size();            //对于之前已经得到的结果,首先复制一份一样的,然后再对其加入新遍历的元素。            for(int j=0;j<size;j++)            {                res.push_back(res[j]);                res.back().push_back(nums[i]);            }        }        return res;    }};

结果:8ms

3、题目的tag提示可以用回溯

class Solution {public:    vector<vector<int>> subsets(vector<int>& nums) {        sort(nums.begin(),nums.end());        vector<vector<int>> res;        vector<int> tmp;        dfs(nums,res,0,tmp);        return res;    }    void dfs(const vector<int>&nums,vector<vector<int> >& res,int length,vector<int>&tmp)    {        res.push_back(tmp);        for(int i=length;i<nums.size();i++)        {            tmp.push_back(nums[i]);            dfs(nums,res,i+1,tmp);            tmp.pop_back();        }    }};

结果:8ms

39. Combination Sum | Difficulty: Medium

Given a set of candidate numbers (C) 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]
]

题意:从一个集合中挑选一些和为target的数组成新的集合。
相关题目:Combination Sum III
思路:
1、还是回溯,套用回溯的模板

class Solution {public:    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {        sort(candidates.begin(),candidates.end());        vector<vector<int>> res;        vector<int> tmp;        dfs(candidates,target,res,tmp,0);            return res;    }    void dfs(const vector<int>candidates,int target,vector<vector<int>>&res,vector<int>&tmp,int begin)    {        if(!target)        {            res.push_back(tmp);            return;        }        for(int i=begin;i!=candidates.size()&&target>=candidates[i];i++)        {            tmp.push_back(candidates[i]);            dfs(candidates,target-candidates[i],res,tmp,i);            tmp.pop_back();        }    }};

结果:24ms

40. Combination Sum II | Difficulty: Medium

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums toT.
Each number in C may only be used once in the combination.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.

For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]

题意:和前面题目很类似,区别在于集合中的元素只能用一次而不是多次。
思路:
1、和前面的题目都是一个模板,因此需要加一些限制条件就行了。
原本答案应该是:[[1,1,6],[1,2,5],[1,7],[2,6]],
返回的答案变成了:[[1,1,6],[1,2,5],[1,7],[1,2,5],[1,7],[2,6]]
问题在哪里呢?没错,有2个1,然后以第二个1开始的时候产生的组合会与之前的产生重复,可以采用集合来存储就能去重,但是还有更好的办法就是价一个判断条件,那么这个条件是什么呢?显然就要对阵下药,如果一个元素既不是开头元素,同时还与它前一个元素相同,这个时候就是遇到了连续两个相同元素,第二个应该跳过,只要在之前的代码中加一句if(i==begin||candidates[i]!=candidates[i-1])在dfs递归调用之前就可以了。

class Solution {public:    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {        sort(candidates.begin(),candidates.end());        vector<vector<int>> res;        vector<int> tmp;        dfs(candidates,target,res,tmp,0);        return res;    }    void dfs(const vector<int>&candidates,int target,vector<vector<int>>& res,vector<int>&tmp,int begin)    {        if(!target)        {            res.push_back(tmp);            return ;        }        if(target<0)    return;        for(int i=begin;i!=candidates.size()&&target>=candidates[i];i++)        {            if(i==begin||candidates[i]!=candidates[i-1])            {            tmp.push_back(candidates[i]);            dfs(candidates,target-candidates[i],res,tmp,i+1);            tmp.pop_back();            }        }    }};

结果:12ms

0 0
原创粉丝点击