Leetcode 78 Subsets + 90 Subsets II 子集

2024-01-13 11:58
文章标签 leetcode ii 子集 90 78 subsets

本文主要是介绍Leetcode 78 Subsets + 90 Subsets II 子集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原题地址:https://leetcode.com/problems/subsets/

题目描述

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.
结果集中不能有重复的子集。

解题思路

这个题可以用动态规划来解,我们每次只需考虑对于某个元素,是否要把它放入到子集中,要么放进去要么不放进去,这样得到的是两个不同的子集。

可以用递归调用,获取其后所有元素的子集,然后遍历子集,把每一个子集添加到结果集中,并并把每一个子集添加当前元素之后再把它添加到当前结果集中。

算法描述

  1. 将数组排序
  2. 对于第i个元素,获取其之后元素(i+1之后的所有元素)的所有子集,然后遍历其所有子集(i+1之后),将每一个子集添加到当前的结果集中,并把每一个子集添加第i个元素之后再把它添加到当前结果集中。

代码

class Solution {
public:vector<vector<int> > subsets(vector<int>& nums) {// 原始数据排序sort(nums.begin(), nums.end());// 返回第0个元素之后的所有元素组成的集合的子集return subsets(nums, 0, nums.size());}// 返回nums数组中第cur个元素及其之后所有元素组成的集合的所有的子集// nums: 原始数据// cur: 当前处理的元素// len: 原始数据长度vector<vector<int> > subsets(vector<int>& nums, int cur, int len) {// 如果当前元素已经超出数据边界,返回一个空集(空集是任意集合的子集)if (cur == len) {vector<vector<int> > ret;vector<int> tmp;ret.push_back(tmp);return ret;}// 获取第cur个元素之后的所有元素组成的集合的所有子集vector<vector<int> > ret = subsets(nums, cur + 1, len);// 先将这些子集添加到结果集中vector<vector<int> > retTmp;copy(ret.begin(), ret.end(), back_inserter(retTmp));// 把每个子集的首位置添加当前元素,然后加入到结果集中for (int i = 0; i < ret.size(); ++i) {vector<int> tmp = ret[i];tmp.insert(tmp.begin(), nums[cur]);retTmp.push_back(tmp);}return retTmp;}
};

运行情况

Status : Accepted
Run Time : 10ms

一点延伸 Leetcode 90 Subsets II


2015/5/14更新

额,今天发现之前考虑过的这种情况就是Leetcode 90的题目内容。下面的代码稍作改动(其实就只是改了个函数名),提交到oj上Accept,不过运行时间不是很好,28ms,看别人大部分分布在16ms左右。暂时先这样吧。


题目中说了,不允许出现重复的子集。由于原始数据中不存在重复的元素,因此子集不重复还是很好做的,那么问题来了,如果原始数据中有重复数据怎么办呢?例如 [1, 1, 2, 3] 用上述程序跑出来结果是:

[]
[3]
[2]
[2, 3]
[1]
[1, 3]
[1, 2]
[1, 2, 3]
[1]
[1, 3]
[1, 2]
[1, 2, 3]
[1, 1]
[1, 1, 3]
[1, 1, 2]
[1, 1, 2, 3]

显然有很多重复的子集。

一个很自然而然的解决思路是,按照上述算法求出子集,然后去除重复的子集即可。

为了方便的去除重复的子集,将所有子集先排序再处理比较容易。

代码如下:

class Solution {
public:vector<vector<int> > subsetsWithDup(vector<int>& nums) {// 原始数据排序sort(nums.begin(), nums.end());// 返回第0个元素之后的所有元素组成的集合的子集vector<vector<int> > ret = subsets(nums, 0, nums.size());// 子集排序sort(ret.begin(), ret.end());// 去重vector<vector<int> >::iterator pre = ret.begin(), cur = pre + 1, last = ret.end();vector<vector<int> > retTmp;retTmp.push_back(ret[0]);while (cur != last) {if ((*pre).size() != (*cur).size()) { // 如果当前子集与前一个非重子集长度不同,则肯定为不同的子集retTmp.push_back(*cur); // 添加当前子集pre = cur; // 更新前一个非重子集++cur; // 指针后移} else { // 如果当前子集与前一个非重子集长度相同,则挨个判断,看是否相同bool same = true;int len = (*pre).size();for (int i = 0; i < len; ++i) {if ((*pre)[i] != (*cur)[i]) { // 如果某个位置元素不同,则两子集不相同same = false;break;}}if (!same) { // 如果当前子集与前一个非重子集不同retTmp.push_back(*cur); // 添加当前子集pre = cur; // 更新前一个非重子集}++cur; // 指针后移}}return retTmp;}vector<vector<int> > subsets(vector<int>& nums, int cur, int len) {// 如果当前元素已经超出数据边界,返回一个空集(空集是任意集合的子集)if (cur == len) {vector<vector<int> > ret;vector<int> tmp;ret.push_back(tmp);return ret;}// 获取第cur个元素之后的所有元素组成的集合的所有子集vector<vector<int> > ret = subsets(nums, cur + 1, len);// 先将这些子集添加到结果集中vector<vector<int> > retTmp;copy(ret.begin(), ret.end(), back_inserter(retTmp));// 把每个子集的首位置添加当前元素,然后加入到结果集中for (int i = 0; i < ret.size(); ++i) {vector<int> tmp = ret[i];tmp.insert(tmp.begin(), nums[cur]);retTmp.push_back(tmp);}return retTmp;}
};

再用[1, 1, 2, 3]来测试,结果为:

[]
[1]
[1, 1]
[1, 1, 2]
[1, 1, 2, 3]
[1, 1, 3]
[1, 2]
[1, 2, 3]
[1, 3]
[2]
[2, 3]
[3]

无重复数据。


// 个人学习记录,若有错误请指正,大神勿喷
// sfg1991@163.com
// 2015-05-12

这篇关于Leetcode 78 Subsets + 90 Subsets II 子集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/601385

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

90、k8s之secret+configMap

一、secret配置管理 配置管理: 加密配置:保存密码,token,其他敏感信息的k8s资源 应用配置:我们需要定制化的给应用进行配置,我们需要把定制好的配置文件同步到pod当中容器 1.1、加密配置: secret: [root@master01 ~]# kubectl get secrets ##查看加密配置[root@master01 ~]# kubectl get se

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

从0到1,AI我来了- (7)AI应用-ComfyUI-II(进阶)

上篇comfyUI 入门 ,了解了TA是个啥,这篇,我们通过ComfyUI 及其相关Lora 模型,生成一些更惊艳的图片。这篇主要了解这些内容:         1、哪里获取模型?         2、实践如何画一个美女?         3、附录:               1)相关SD(稳定扩散模型的组成部分)               2)模型放置目录(重要)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk