【Subsets】cpp
题目:
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的更多相关文章
- leetcode 【 Subsets 】python 实现
题目: Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset mus ...
- 【Permutations】cpp
题目: Given a collection of numbers, return all possible permutations. For example,[1,2,3] have the fo ...
- 【Anagrams】 cpp
题目: Given an array of strings, return all groups of strings that are anagrams. Note: All inputs will ...
- 蓝桥杯 【dp?】.cpp
题意: 给出一个2*n的方格,当刷完某一个方格的漆后可以且只可以走到相邻的任何一格,即上 下 左 右 左上 左下 右上 右下.可以从任意一个格子开始刷墙,问有多少种刷法,因为随着n的增大方案数会变多, ...
- 【Triangle 】cpp
题目: Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjace ...
- 【N-Queens】cpp
题目: The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two que ...
- 【Combinations】cpp
题目: Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For ex ...
- 【Candy】cpp
题目: There are N children standing in a line. Each child is assigned a rating value. You are giving c ...
- 【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 = ...
随机推荐
- POJ C++程序设计 编程题#3 编程作业—文件操作与模板
编程题#3: 整数的输出格式 来源: POJ(Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 1000kB 描述 利 ...
- 查看Linux系统版本信息
一.查看Linux内核版本命令(两种方法): 1.cat /proc/version [root@S-CentOS home]# cat /proc/versionLinux version 2.6. ...
- Date and Time in PeopleCode
Setting a Date to Null in PeopleCode To set a date to null in PeopleCode either use the SetDefault() ...
- 调用WCF Data Service的几点Tips
使用Linq实现sql in statement的时候,用EF的时候可以通过Contains.Exists的方法实现.但是在使用WCF Data Service的context的时候,会报不支持该方法 ...
- FileSystemWatcher用法详解
FileSystemWatcher控件主要功能: 监控指定文件或目录的文件的创建.删除.改动.重命名等活动.可以动态地定义需要监控的文件类型及文件属性改动的类型. 1.常用的几个基本属性: (1) P ...
- Ajax异步刷新局部页面的小李子
看到下面那幅图没有,我们要的是当点击确定以后,根据条形码搜索出商品信息,并且异步刷新右边页面:
- [C#] Extension Method 扩展方法
当我们引用第三方的DLL.或者Visual Studio自己的库的时候,或许会发现这样的一个情况,如果这个类型有一个XX的方法就好了.这时候我们可以用到扩展方法,是我们的代码更加灵活和高效. 这里我举 ...
- Java transient volatile关键字(转)
Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...
- emlog模板制作帮助手册
emlog基本模板文件 必须文件: main.css: CSS(样式表)文件 log_list.php: 日志列表页模板 echo_log.php: 日志页模板 page.php: 页面(page)模 ...
- WebService IIS 部署
刚刚开始接触c#怎么发布程序都搞不定,经过查看网上同仁的资料,自己写了个Webservice发布了下 1.首先自己写好程序,鼠标选中所写Webservice程序,单击鼠标右键-------->发 ...