93.复原IP地址

卡哥建议:本期本来是很有难度的,不过 大家做完 分割回文串 之后,本题就容易很多了

题目链接/文章讲解:https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html

    视频讲解:https://www.bilibili.com/video/BV1XP4y1U73i/

做题思路:

切割问题可以抽象为树型结构,如图:

 

本题明确要求只会分成4段,所以不能用切割线切到最后作为终止条件,而是分割的段数作为终止条件。

pointNum表示逗点数量,pointNum为3说明字符串分成了4段了。然后验证一下第四段是否合法,如果合法就加入到结果集里

131.分割回文串中已经讲过在循环遍历中如何截取子串。

for (int i = startIndex; i < s.size(); i++)循环中 [startIndex, i] 这个区间就是截取的子串,需要判断这个子串是否合法。如果合法就在字符串后面加上符号.表示已经分割。如果不合法就结束本层循环,

主要考虑到如下三点:

  • 段位以0为开头的数字不合法
  • 段位里有非正整数字符不合法
  • 段位如果大于255了不合法

本题代码:

 1 class Solution {
2 private:
3 vector<string> result;// 记录结果
4 // startIndex: 搜索的起始位置,pointNum:添加逗点的数量
5 void backtracking(string& s, int startIndex, int pointNum) {
6 if (pointNum == 3) { // 逗点数量为3时,分隔结束
7 // 判断第四段子字符串是否合法,如果合法就放进result中
8 if (isValid(s, startIndex, s.size() - 1)) {
9 result.push_back(s);
10 }
11 return;
12 }
13 for (int i = startIndex; i < s.size(); i++) {
14 if (isValid(s, startIndex, i)) { // 判断 [startIndex,i] 这个区间的子串是否合法
15 s.insert(s.begin() + i + 1 , '.'); // 在i的后面插入一个逗点
16 pointNum++;
17 backtracking(s, i + 2, pointNum); // 插入逗点之后下一个子串的起始位置为i+2
18 pointNum--; // 回溯
19 s.erase(s.begin() + i + 1); // 回溯删掉逗点
20 } else break; // 不合法,直接结束本层循环
21 }
22 }
23 // 判断字符串s在左闭又闭区间[start, end]所组成的数字是否合法
24 bool isValid(const string& s, int start, int end) {
25 if (start > end) {
26 return false;
27 }
28 if (s[start] == '0' && start != end) { // 0开头的数字不合法
29 return false;
30 }
31 int num = 0;
32 for (int i = start; i <= end; i++) {
33 if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法
34 return false;
35 }
36 num = num * 10 + (s[i] - '0');
37 if (num > 255) { // 如果大于255了不合法
38 return false;
39 }
40 }
41 return true;
42 }
43 public:
44 vector<string> restoreIpAddresses(string s) {
45 result.clear();
46 if (s.size() < 4 || s.size() > 12) return result; // 算是剪枝了
47 backtracking(s, 0, 0);
48 return result;
49 }
50 };

78.子集

卡哥建议:子集问题,就是收集树形结构中,每一个节点的结果。 整体代码其实和 回溯模板都是差不多的。

题目链接/文章讲解:https://programmercarl.com/0078.%E5%AD%90%E9%9B%86.html

    视频讲解:https://www.bilibili.com/video/BV1U84y1q7Ci

做题思路:

以示例中nums = [1,2,3]为例把求子集抽象为树型结构,如下:

从图中红线部分,可以看出遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合。

   如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!

数组path为子集收集元素,二维数组result存放子集组合。

剩余集合为空的时候,就是叶子节点。就是startIndex已经大于数组的长度了,就终止了,因为没有元素可取了,

其实可以不需要加终止条件,因为startIndex >= nums.size(),本层for循环本来也结束了。

   求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树。

本题代码:

 1 class Solution {
2 private:
3 vector<vector<int>> result;
4 vector<int> path;
5 void backtracking(vector<int>& nums, int startIndex) {
6 result.push_back(path); // 收集子集,要放在终止添加的上面,否则会漏掉自己
7 if (startIndex >= nums.size()) { // 终止条件可以不加
8 return;
9 }
10 for (int i = startIndex; i < nums.size(); i++) {
11 path.push_back(nums[i]);
12 backtracking(nums, i + 1);
13 path.pop_back();
14 }
15 }
16 public:
17 vector<vector<int>> subsets(vector<int>& nums) {
18 result.clear();
19 path.clear();
20 backtracking(nums, 0);
21 return result;
22 }
23 };

90.子集II

卡哥建议:大家之前做了 40.组合总和II 和 78.子集 ,本题就是这两道题目的结合,建议自己独立做一做,本题涉及的知识,之前都讲过,没有新内容。

题目链接/文章讲解:https://programmercarl.com/0090.%E5%AD%90%E9%9B%86II.html

   视频讲解:https://www.bilibili.com/video/BV1vm4y1F71J

做题思路:

这道题目和78.子集区别就是集合里有重复元素了,而且求取的子集要去重。

用示例中的[1, 2, 2] 来举例,如图所示: (注意去重需要先对集合排序)

从图中可以看出,本题要树层去重,同一树层上重复取2 就要过滤掉,同一树枝上就可以重复取2,因为同一树枝上元素的集合才是唯一子集!

本题代码:

 1 class Solution {
2 private:
3 vector<vector<int>> result;
4 vector<int> path;
5 void backtracking(vector<int>& nums, int startIndex, vector<bool>& used) {
6 result.push_back(path);
7 for (int i = startIndex; i < nums.size(); i++) {
8 // used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
9 // used[i - 1] == false,说明同一树层candidates[i - 1]使用过
10 // 而我们要对同一树层使用过的元素进行跳过
11 if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
12 continue;
13 }
14 path.push_back(nums[i]);
15 used[i] = true;
16 backtracking(nums, i + 1, used);
17 used[i] = false;
18 path.pop_back();
19 }
20 }
21
22 public:
23 vector<vector<int>> subsetsWithDup(vector<int>& nums) {
24 result.clear();
25 path.clear();
26 vector<bool> used(nums.size(), false);
27 sort(nums.begin(), nums.end()); // 去重需要排序
28 backtracking(nums, 0, used);
29 return result;
30 }
31 };

代码随想录算法训练营第二十八天| 93.复原IP地址 78.子集 90.子集II的更多相关文章

  1. LeetCode算法训练 93.复原IP地址 78.子集 90.子集II

    欢迎关注个人公众号:爱喝可可牛奶 LeetCode算法训练 93.复原IP地址 78.子集 90.子集II LeetCode 93. 复原 IP 地址 分析 字符串全部由数字组成,ipv4每一段数字不 ...

  2. 代码随想录算法训练营第二天| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

    977.有序数组的平方 :https://leetcode.cn/problems/squares-of-a-sorted-array/ 心得:周末再写... public class Solutio ...

  3. Java实现 LeetCode 93 复原IP地址

    93. 复原IP地址 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 示例: 输入: "25525511135" 输出: ["255.255.11. ...

  4. 代码随想录算法训练营day01 | leetcode 704/27

    前言   考研结束半个月了,自己也简单休整了一波,估了一下分,应该能进复试,但还是感觉不够托底.不管怎样,要把代码能力和八股捡起来了,正好看到卡哥有这个算法训练营,遂果断参加,为机试和日后求职打下一个 ...

  5. leetcode 93 复原IP地址

    IP地址,分成四段,每段是0-255,按照每段的长度分别为1,2,3下一段长度分别1,2,3再下一段......进行递归遍历,能满足条件的假如res中.比较难想到的就是假如有一段是三位的010是不符合 ...

  6. leetcode刷题-93复原IP地址

    题目 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 '.' 分隔. 示例: 输入: &q ...

  7. 代码随想录算法训练营day06 | leetcode 242、349 、202、1

    基础知识 哈希 常见的结构(不要忘记数组) 数组 set (集合) map(映射) 注意 哈希冲突 哈希函数 LeetCode 242 分析1.0 HashMap<Character, Inte ...

  8. 代码随想录算法训练营day03 | LeetCode 203/707/206

    基础知识 数据结构初始化 // 链表节点定义 public class ListNode { // 结点的值 int val; // 下一个结点 ListNode next; // 节点的构造函数(无 ...

  9. 代码随想录算法训练营day02 | leetcode 977/209/59

    leetcode 977   分析1.0:   要求对平方后的int排序,而给定数组中元素可正可负,一开始有思维误区,觉得最小值一定在0左右徘徊,但数据可能并不包含0:遂继续思考,发现元素分布有三种情 ...

  10. 代码随想录算法训练营day22 | leetcode 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点

    LeetCode 235. 二叉搜索树的最近公共祖先 分析1.0  二叉搜索树根节点元素值大小介于子树之间,所以只要找到第一个介于他俩之间的节点就行 class Solution { public T ...

随机推荐

  1. 禁用input自动补全,模拟type=password输入字符显示为星号

    最近遇到一个想禁用浏览器的密码自动补全的功能,翻遍了整个技术论坛大多使用用auto-complete="new-password"但是本人测试不怎么管用,所有又找到了如下几种方法, ...

  2. .cur 图片加载提示 You may need an appropriate loader to handle this file type

    最近一个gis 项目需要加载一个.cur的图标,但是编译时提示 You may need an appropriate loader to handle this file type, current ...

  3. RabbitMQ 工作模式介绍

    RabbitMQ 工作模式介绍 1.Hello World RabbitMQ 是一个消息代理:它接受并转发消息.您可以将其视为邮局:当您将要邮寄的邮件放入邮箱时,您可以确定信使最终会将邮件交付给您的收 ...

  4. RSA 加密解密

    from Crypto.Util.number import bytes_to_long, long_to_bytes, getPrime import libnum # 一.取两个素数 p = ge ...

  5. Rust 通用编程概念

    通用编程概念 变量.基本类型.函数.控制流 变量与可变性 rust中的变量默认是不可变的,这样是为了能够让你安全并且方便地写出复杂.甚至并行的代码. 当一个变量是不可变时,一旦它绑定到了某个值上面,这 ...

  6. @Retention元注解的使用

    @Retention注解标记其他的注解用于指明标记的注解保留策略:先看Java SE 8中@Target是如何声明的: package java.lang.annotation; public enu ...

  7. 面试官:“同学,你做的这几个项目都不错。但怎么问QPS你就胡说呢?”

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 这位同学,你比上一位面试者好多了,你的简历中做的几个项目都不错.既有业务项目,也有技术项目,看 ...

  8. 【Netty】01 - NIO

    一. NIO 基础 non-blocking io 非阻塞 IO 1. 三大组件 1.1 Channel & Buffer channel 有一点类似于 stream,它就是读写数据的双向通道 ...

  9. 一篇讲懂Java运行类型、编译类型和多态(面向对象语言精髓之一)

    对象:运行类型.编译类型和多态 1.搞清楚面向对象的运行类型和编译类型就掌握了对象的精髓,我们用举个例子 class Father { Father() { System.out.println(&q ...

  10. 让AI支持游戏AI模型:从经典AI算法到最新技术的应用

    目录 20. 让 AI 支持游戏AI模型:从经典 AI 算法到最新技术的应用 1. 引言 2. 技术原理及概念 2.1 基本概念解释 2.2 技术原理介绍 2.2.2 最新技术介绍 3. 实现步骤与流 ...