当前位置: 首页 > news >正文

day24

93. 复原 IP 地址 - 力扣(LeetCode)

class Solution {
public:vector<string> res;bool isValid(string s, int start , int end){if(start > end) return false;if(s[start] == '0' && start != end) return false;int num = 0;for(int i = start; i <= end; i++){if(s[i] > '9' || s[i] < '0') return false;num = num * 10 + s[i] - '0';if(num > 255) return false;} return true;}void dfs(string s, int index, int pointNUum){if(pointNUum == 3){if(isValid(s, index, s.size() -1)){res.push_back(s);}return;}for(int i = index; i < s.size(); i++){if(isValid(s,index, i)){s.insert(s.begin() + i + 1, '.');pointNUum++;dfs(s, i+2, pointNUum);pointNUum--;s.erase(s.begin()+1+i);} else {break;}}}vector<string> restoreIpAddresses(string s) {dfs(s, 0 ,0);return res;}
};

78. 子集 - 力扣(LeetCode)

class Solution {
public:vector<vector<int>> subsets(vector<int>& nums) {vector<vector<int>> ans;vector<int> path;int n = nums.size();auto dfs = [&](this auto && dfs, int index){if(index == n){ans.push_back(path);return;}dfs(index+1); // 不选这个数字path.push_back(nums[index]);//选dfs(index+1);path.pop_back();};dfs(0);return ans;}
};

一句话核心

对每个元素做“两选一”:要它 / 不要它。从左到右把这 n 次二选一做完,就天然枚举出了 2^n 个子集;到头就把当前选择路径记录下来。

状态与不变式

在代码里,我们用两个量描述“走到哪儿了、当前拿了谁”:

  • i:正在决定第 i 个元素是否取用(范围 0..n)。

  • path:目前已经“选进来”的元素(就是正在构造的那个子集)。

每进一层递归,就在第 i 个元素上做决定;每回到上一层,就撤销刚才的决定(回溯)。

分支(决策)怎么长

nums[i] 有两条路:

  1. 不选它:self(i+1)path 不变

  2. 它:先 path.push_back(nums[i]),然后 self(i+1),回来时 path.pop_back()

i == n,说明所有元素都做完“二选一”了,此时 path 就是一个完整子集,收集进 ans

你可以把整棵搜索树看成一个深度为 n 的二叉树:
每一层对应一个元素,左边“不选”,右边“选”,叶子结点就是一个子集。

为什么能覆盖所有子集、且不重不漏?

  • 每个元素恰好被处理一次(要/不要),因此所有组合都被覆盖;

  • 没有重复:因为每个元素的“取舍”只做一次,不会从别的路径再来一次;

  • 包含空集:如果一路都“不选”,到 i==npath 为空,也会被收集;

  • 包含全集:如果一路都“选”,path 就是所有元素,也会被收集。

和“排列/组合”有什么区别?

  • 子集不关心顺序({1,2}{2,1} 同一个),所以我们只按原顺序往后做“要/不要”,不会调换位置;

  • 排列要考虑位置顺序,就需要“已用标记 + 枚举未用元素”;

  • **组合(选 k 个)**是在子集的框架上再加一个“已选数量==k 才收集”的条件。

走一遍小例子(nums = [1,2,3]

深度优先的顺序大致如下([] 表示 path):

  1. 不选1 → 不选2 → 不选3 → 收集 []

  2. 不选1 → 不选2 → 选3 → 收集 [3]

  3. 不选1 → 选2 → 不选3 → 收集 [2]

  4. 不选1 → 选2 → 选3 → 收集 [2,3]

  5. 选1 → 不选2 → 不选3 → 收集 [1]

  6. 选1 → 不选2 → 选3 → 收集 [1,3]

  7. 选1 → 选2 → 不选3 → 收集 [1,2]

  8. 选1 → 选2 → 选3 → 收集 [1,2,3]

正好是 2^3 = 8 个子集,全覆盖、不重不漏。

复杂度

  • 时间O(n · 2^n);共有 2^n 个子集,每个子集输出平均要拷贝/遍历 O(n)。

  • 空间:递归深度 + 路径 O(n)

这段代码里的小细节(为何这样写更顺)

  • ans.reserve(1<<n)path.reserve(n):预分配减少扩容;

  • 回溯的“选 → 递归 → pop”是原地修改再还原,比“复制一份再传”更省内存;

90. 子集 II - 力扣(LeetCode)

class Solution {
public:vector<vector<int>> subsetsWithDup(vector<int>& nums) {sort(nums.begin(), nums.end());vector<vector<int>> ans;vector<int> path;int n = nums.size();auto dfs = [&](this auto && dfs, int index)->void{ans.push_back(path);for(int i = index; i < n; i++){if(i > index && nums[i] == nums[i-1]) continue;path.push_back(nums[i]);dfs(i+1);path.pop_back();}};dfs(0);return ans;}
};

http://www.dtcms.com/a/344688.html

相关文章:

  • Nginx(一)认识Nginx
  • 一级指针遍历二维数组
  • 3-2〔OSCP ◈ 研记〕❘ WEB应用攻击▸WEB安全防护体系
  • Python Flask快速实现163邮箱发送验证码
  • 防爆自动气象监测设备:高危环境的 “安全堡垒”
  • 高防cdn如何缓存网页静态资源
  • Nacos docker 版本配置kingbase 人大金仓 达梦 数据库
  • 定时器中断学习汇总
  • 从快递运输与排队办事,看实时通信的MVP方案与增强方案
  • V380E telnet远程连接导致rce漏洞复现(CVE-2025-7503)
  • 【解决办法】wps的word文档编辑时字体的下方出现灰色的底色如何删除
  • 【字节拥抱开源】字节豆包团队开源豆包OSS大模型
  • 数学建模--Topsis
  • LLM实践系列:利用LLM重构数据科学流程04 - 智能特征工程
  • Redis事务与锁的顺序抉择:事务里加锁 vs 先锁再事务的“微妙差异”分享
  • C#自定义工具类-时间日期工具类
  • 【python与生活】如何用Python写一个简单的自动整理文件的脚本?
  • 常用 CMake 内置变量合集与说明
  • Python 环境变量:从基础到实战的灵活配置之道
  • Logstash——输出(Output)
  • Jenkins自动化部署服务到Kubernetes环境
  • 云计算学习100天-第27天
  • python程序函数计时
  • unity资源领取反作弊工具加密器
  • 递归思路:从DFS到二叉树直径的实战(通俗易懂)
  • redis设置密码及配置conf
  • OpenSCA开源社区每日安全漏洞及投毒情报资讯|21th Aug. , 2025
  • 异常值检测:孤立森林模型(IsolationForest)总结
  • 并发编程:浅析LockSupport工具
  • 大数据世界的开拓者:深入浅出MapReduce分布式计算经典范式