题目:

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. s3c6410_时钟初始化

    参考: 1)<USER'S MANUAL-S3C6410X>第三章 SYSTEM CONTROLLER 2)u-boot/board/samsumg/smdk6410/lowlevel_i ...

  2. 2_JavaScript日期格式化

          第二章 JavaScript 时间格式化 2.1 Ticks 转换为常规日期 2.2 常规日期格式化 <input type="button" value=&qu ...

  3. iOS网络通讯——监测网络状态:Reachability(可达性)

    1.iOS平台是按照一直有网络连接的思路来设计的,开发者利用这一特点创造了很多优秀的第三方应用.大多数的iOS应用都需要联网,甚至有些应用严重依赖网络,没有网络就无法正常工作. 2.在你的应用尝试通过 ...

  4. silverlight嵌套html不能输入中文问题

    1.xaml <UserControl xmlns:SilverlightClient="clr-namespace:SilverlightClient" x:Class=& ...

  5. sed命令实战

    删除所有的空行,并在每行后面增加一个空行 sed '/^$/d;G' /etc/fstab 将每一行前导的“空白字符”(空格,制表符)删除 sed 's/^[\t ]*//' file 将文本中的 a ...

  6. Oozie和Azkaban的技术选型和对比

    1 两种调度工具功能对比图 下面的表格对上述2种hadoop工作流调度器的关键特性进行了比较,尽管这些工作流调度器能够解决的需求场景基本一致,但在设计理念,目标用户,应用场景等方面还是存在区别 特性 ...

  7. SAE平台的文件I/O处理

          用过SAE平台的朋友应该知道,出于平台安全性的考虑,SAE限制了用户对于本地IO的使用.但这样对于一些传统的PHP项目,也许带来了很多不便,因为它们都或多或少的有对本地IO的操作,像Sma ...

  8. UCOS2_STM32F1移植详细过程(四)

    Ⅰ.概述 上一篇文章是讲述uC/OS-II Ports下面os_cpu_a.asm.os_cpu_c.c和os_cpu.h文件底层端口代码的移植(修改)和说明,接着上一篇文章来讲述关于UCOS移植应用 ...

  9. Tostring记录,方便自己查看

    C 货币 2.5.ToString("C") ¥2.50 D 十进制数 25.ToString("D5") 00025 E 科学型 25000.ToString ...

  10. 扯一扯前端css的整体架构设计:(2)base基础类的那些事儿

    周一下午在实验室写了第一篇博文,有几个人捧场,那咱就得接着下去啊.然后我觉得现在写的内容更多的偏向于谈一下我对于前端css架构的理解和前端经验的一个小总结,所以就把标题里原来的[项目总结]给删掉了.但 ...