题目:

Given a set of distinct integers, nums, return all possible subsets.

Note:

  • Elements in a subset must be in non-descending order.
  • 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],
[]
]

代码:

class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
const int len = nums.size();
std::sort(nums.begin(), nums.end());
vector<vector<int> > ret = Solution::subsubsets(nums, , len-);
vector<int> none;
ret.push_back(none);
return ret;
}
static vector<vector<int> > subsubsets(vector<int>& nums, int begin, int end)
{
vector<vector<int> > ret;
if ( begin>end ) return ret;
for ( int i = begin; i <=end; ++i )
{
// puts the curr value in
vector<int> curr;
curr.push_back(nums[i]);
ret.push_back(curr);
// get the subset
vector<vector<int> > subset = Solution::subsubsets(nums, i+, end);
for ( int j = ; j < subset.size(); ++j )
{
//ret.push_back(subset[j]);
subset[j].insert(subset[j].begin(), nums[i]);
ret.push_back(subset[j]);
}
}
return ret;
}
};

tips:

每层递归的任务是活的传入数组的全部子集

1. 留出第i个元素

2. 把i+1到end的元素送到下一层递归

3. 递归终止条件是begin>end

返回下一集全部子集后,算上第i个元素后的全部集合如下:

1)第i个元素单独算一个

2)第i个元素 + 子集中每个元素

这样递归到第0个元素,就得到了全部的非空子集;再根据题目要求补上空集。

============================================

完成之后觉得好像哪里不对。{1,2,3} 如果留下了1传入{2,3}时,这个过程中已经获得了{2,3}全部子集。

修改后的代码如下:

class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
const int len = nums.size();
std::sort(nums.begin(), nums.end());
vector<vector<int> > ret = Solution::subsubsets(nums, , len-);
vector<int> none;
ret.push_back(none);
return ret;
}
static vector<vector<int> > subsubsets(vector<int>& nums, int begin, int end)
{
vector<vector<int> > ret;
if ( begin>end ) return ret;
// puts the curr value in
vector<int> curr;
curr.push_back(nums[begin]);
ret.push_back(curr);
// get the subset
vector<vector<int> > subset = Solution::subsubsets(nums, begin+, end);
for ( int j = ; j < subset.size(); ++j )
{
ret.push_back(subset[j]);
subset[j].insert(subset[j].begin(), nums[begin]);
ret.push_back(subset[j]);
}
return ret;
}
};

tips:

这个版本整理了逻辑误区。

============================

又学习了一个深搜版本的代码,如下:

class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int> > ret;
std::sort(nums.begin(), nums.end());
vector<int> tmp;
Solution::dfs(ret, nums, , tmp);
return ret;
}
static void dfs(vector<vector<int> >& ret, vector<int>& nums, int index, vector<int>& tmp)
{
if ( index==nums.size() ) { ret.push_back(tmp); return; }
tmp.push_back(nums[index]);
Solution::dfs(ret, nums, index+, tmp);
tmp.pop_back();
Solution::dfs(ret, nums, index+, tmp);
}
};

Tips:

把集合元素想象成一个二叉树,如下

每层处理一个元素;往左分支代表加入这个元素;往右分支代表不加入这个元素;最终叶子节点就是全部子集。

这里需要维护一个层次变量index看是否到叶子了。

================================

再学习一个简单迭代的解法,代码如下:

class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int> > ret;
std::sort(nums.begin(), nums.end());
vector<int> none;
ret.push_back(none);
for ( size_t i = ; i < nums.size(); ++i )
{
vector<vector<int> > subset = ret;
for ( size_t j = ; j < subset.size(); ++j )
{
subset[j].push_back(nums[i]);
ret.push_back(subset[j]);
}
}
return ret;
}
};

tips:

1. 用subset记录上一轮结束后,所有子集;

2. 考虑subset中所有元素,加上nums[i]元素后多出来的集合,补充到ret中

这里注意,利用一个中间变量subset来保存ret上一轮的结果(或者保存上一组的指针)。

仔细想想,这套代码的思路与最开始递归代码的思路正好是逆向的:

1)递归的代码是留出来当前元素,去寻找其余所有元素组成的子集集合

2)迭代的代码是每次添加当前元素,并更新所有子集集合,直到添加入最后一个元素

================================================

第二次过这道题,首选的解法是简单迭代解法。这种方法的精髓是在于有一个none,这样每次都能把新元素单独列进来。

class Solution{
public:
static vector<vector<int> > subsets(vector<int>& nums)
{
sort(nums.begin(), nums.end());
vector<vector<int> > ret;
vector<int> none;
ret.push_back(none);
for ( int i=; i<nums.size(); ++i )
{
vector<vector<int> > tmp = ret;
for ( int j=; j<tmp.size(); ++j )
{
tmp[j].push_back(nums[i]);
ret.push_back(tmp[j]);
}
}
return ret;
}
};

还用了dfs的解法。

class Solution {
public:
vector<vector<int> > subsets(vector<int>& nums)
{
sort(nums.begin(), nums.end());
vector<vector<int> > ret;
vector<int> tmp;
Solution::dfs(nums, ret, , tmp);
return ret;
}
static void dfs(
vector<int>& nums,
vector<vector<int> >& ret,
int index,
vector<int>& tmp)
{
if ( index==nums.size() )
{
ret.push_back(tmp);
return;
}
tmp.push_back(nums[index]);
Solution::dfs(nums, ret, index+, tmp);
tmp.pop_back();
Solution::dfs(nums, ret, index+, tmp);
}
};

复习了dfs模板的写法。这个有个点需要注意,就是返回上一层时,一定要保证tmp是‘干净的’,因此,要有pop_back()这个动作。

【Subsets】cpp的更多相关文章

  1. leetcode 【 Subsets 】python 实现

    题目: Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset mus ...

  2. 【Permutations】cpp

    题目: Given a collection of numbers, return all possible permutations. For example,[1,2,3] have the fo ...

  3. 【Anagrams】 cpp

    题目: Given an array of strings, return all groups of strings that are anagrams. Note: All inputs will ...

  4. 蓝桥杯 【dp?】.cpp

    题意: 给出一个2*n的方格,当刷完某一个方格的漆后可以且只可以走到相邻的任何一格,即上 下 左 右 左上 左下 右上 右下.可以从任意一个格子开始刷墙,问有多少种刷法,因为随着n的增大方案数会变多, ...

  5. 【Triangle 】cpp

    题目: Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjace ...

  6. 【N-Queens】cpp

    题目: The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two que ...

  7. 【Combinations】cpp

    题目: Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For ex ...

  8. 【Candy】cpp

    题目: There are N children standing in a line. Each child is assigned a rating value. You are giving c ...

  9. 【4Sum】cpp

    题目: Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = ...

随机推荐

  1. MySQL的存储引擎整理

    01.MyISAM MySQL 5.0 以前的默认存储引擎.MyISAM 不支持事务.也不支持外键,其优势是访问的速度快,对事务完整性没有要求或者以SELECT.INSERT 为主的应用基本上都可以使 ...

  2. 在Linux命令行窗口中,怎么向上翻页?

    解决方法:本机环境:vmware linux Redhat9.0版本 使用:Shift + PageUp 和 Shift + PageDown向上和向下翻页

  3. 【转】IE11的变化

    1.navigator.userAgent中不再包含“MSIE”关键字 2.用javascript的判断是否是IE11的方法是: var isIE11 = (sUserAgent.toLowerCas ...

  4. js各种宽高(2)

    在javascript和jquery中,都有对各种高度的写法,在这里,我们就着重讲一下窗口.文档等高度的理解.(宽度和高度差不多!) jquery的各种高度 首先来说一说$(document)和$(w ...

  5. Python在金融,数据分析,和人工智能中的应用

    Python在金融,数据分析,和人工智能中的应用   Python最近取得这样的成功,而且未来似乎还会继续下去,这有许多原因.其中包括它的语法.Python开发人员可用的科学生态系统和数据分析库.易于 ...

  6. php生成随机字符串和验证码的类

    网上有很多的php随机数与验证码的代码与文章,真正适用的没有几个. 索性自己搞一个吧. 开始本节的php教程 吧,以下代码的实现,主要做到可以很好区分一个get_code(),另一个create_ch ...

  7. mysql忘记root密码拯救方法(flush privileges)

    修改的用户都以root为列.一.拥有原来的myql的root的密码: 方法一:在mysql系统外,使用mysqladmin# mysqladmin -u root -p password " ...

  8. python 中 input 和 raw_input 的区别

    input会假设输入的信息是合法的python表达式,例如,输入一个人名,Diesel,input会认为这是一个变量,必须加上引号,比如“Diesel”: 而raw_input会把所有的输入当作原始数 ...

  9. Linux驱动开发之字符设备模板

    /***************************** ** 驱动程序模板* 版本:V1* 使用方法(末行模式下):* :%s/xxx/"你的驱动名称"/g********* ...

  10. Factory Girl使用

    1.使用Rspec,详见http://www.cnblogs.com/fanxiaopeng/p/3563772.html 2.在gemfile中添加 #Gemfile group :developm ...