【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 = ...
随机推荐
- mysql多实例安装脚本
#! /bin/bash # v.mysql-5.6.30-linux-glibc2.5-x86_64.tar.gz # only install master mysql # time:2016-0 ...
- s3c6410_u-boot-2010.03移植【续】
本文接上一篇:http://www.cnblogs.com/tanghuimin0713/p/3965528.html 6.3)重新编译,烧写,运行 U-Boot - ::) for SMDK6410 ...
- 内核linux-3.4.2支持dm9000
当前烧写: fs: nfs 30000000 192.168.1.17:/work/nfs_root/first_fs_mdev.yaffs2 //这里不能使用nfs挂载,只能直 ...
- C# .Net三层架构[转]
C# .Net三层架构[转] 编写人:CC阿爸 2014-3-14 希望朋友们留下自己对三层架构的理解... 三层体系结构的概念 用户界面表示层(USL) 业务逻辑层(BLL) 数据访问层(D ...
- 封装Html5 Fullscreen API
复制前言: 使用新的全屏 API,可以将用户的注意力导向特定元素,同时隐藏背景或转移对其他应用的注意力.因为W3C全屏规范还未达到最终版本,所以大多数浏览器供应商都使用唯一标识符为 API 添加前缀. ...
- PHP 文件上传服务端及客户端配置参数说明
文件上传服务器端配置: ·file_uploads = On, 支持HTTP上传 ·upload_tmp_dir = , 临时文件保存的目录 ·upload_max_filesize=2M, 允许上传 ...
- php读取excel文件 更新修改excel
php读取excel文件示例,还有更新修改功能. 代码: //模板存放目录 $dir = $DOCUMENT_ROOT.'/backoffice/admin/oemcheck/'; $template ...
- 基于OWIN WebAPI
http://www.cnblogs.com/Irving/p/4607104.html http://www.cnblogs.com/xishuai/p/aspnet-webapi-owin-oau ...
- 安装wampserver出现“The Program can't start because MSVCR110.dll is missing from your computer. Try reinstalling the program to fix this problem”
问题描述: 今天安装wampserver的时候出现"The Program can't start because MSVCR110.dll is missing from your com ...
- C,C++回文字符串判断(字符串指针的用法)
功能:输入一个字符串,判断是否为回文. 主要锻炼指针的用法. 1.C版 #include<stdio.h> int main() { ]; char a; ,flag=; while((a ...