题目:

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. python简单的发送邮件

    python 利用smtplib来发送邮件,具体的代码如下 一. 编辑smtp_v2.py vim /home/python/smtp_v2.py #!/usr/bin/env python # -* ...

  2. activiti搭建(五)BPMN介绍

    转载请注明源地址:http://www.cnblogs.com/lighten/p/5931207.html 对于BPMN我也不是十分清楚,目前也只是因为对于Modeler中不熟悉的组件查询,来对这部 ...

  3. POJ C++程序设计 编程题#3 编程作业—运算符重载

    编程题 #3 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 写一个二维数组 ...

  4. Silverlight动态设置WCF服务Endpoint

    2013-02-02 05:57 by jv9, 1763 阅读, 3 评论, 收藏, 编辑 去年12月收到一位朋友的邮件,咨询Silverlight使用WCF服务,应用部署后一直无法访问的问题,通过 ...

  5. PHP导出excel文件

    现在教教你如何导入excel文件: 在我的文件储存里面有一个com文件夹的,将其解压放在ThinkPHP/Library/文件夹里面,然后就是写控制器啦!去调用这个插件: <?php names ...

  6. php设计模式之Proxy(代理模式)和Facade(外观)设计模式

    Proxy(代理模式)和Facade(外观)设计模式它们均为更复杂的功能提供抽象化的概念,但这两种实现抽象化的过程大不相同 Proxy案例中,所有的方法和成员变量都来自于目标对象,必要时,该代理能够对 ...

  7. Ubuntu14.04 切换root账户su root失败解决办法

    原因是需要备份一个vimrc,可是cp就提示Permission denied. su root就提示su: Authentication failure 解决办法: sudo passwd root ...

  8. Java求和

    用while结构求0~100的整数数字之和. 代码如下: public class WhileDemo { public static void main(String[] args) { int l ...

  9. openerp 常见问题 OpenERP为什么选择了时区后时间还是不对?(转载)

    OpenERP为什么选择了时区后时间还是不对? 原文地址:http://cn.openerp.cn/%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9%E4%B ...

  10. JavaScrip拖动动画中的常见BUG

    经常我们在用JS辛苦写完一个拖动效果之后 ,发现有各种无法用JS解决的BUG.比如拖动时DOM元素中的内容会变蓝,鼠标的指示会变为一个小+号,或disable的样式,通常这种情况一发生,我们的拖动效果 ...