代码随想录第28天 | 93.复原IP地址 、 78.子集 、 90.子集II

news2024/10/7 8:20:30

一、前言:

参考文献:代码随想录

今天的主题内容是回溯算法,这一章的干货很多,我需要慢慢的品味,不单单只是表象,还需要研究深层原理。

二、复原IP地址

1、思路:

(1)首先还是确定返回值和参数:

void backtracking(string &s, int startIndex, int pointSum)

这里比往常多了一个pointSum,这个是来判断是否符合ip格式的一个标志,也就是记录这个s中存在多少个".";

(2)终止条件如下:

// pointsum是用来判断这个字符串中存在多少个"."如果有了三个,就说明满足IP格式了
        if (pointSum == 3) {
            if (isValud(s, startIndex, s.size() - 1)) {
            // 这里还有一个条件就是判断最后的一段是否符合IP要求
                result.push_back(s);
            }
            return;
        } 

这里首先要判断是否有三个”.“,存在之后,再判断最后的那一段是否符合IP的格式,然后才能插入,如果不符合那就直接return回溯了。

(3)单层递归逻辑:

for (int i = startIndex; i < s.size(); i++) {
            if (isValud(s, startIndex, i)) {
                s.insert(s.begin() + i + 1, '.'); // 插入"."
                pointSum++;
                backtracking(s, i + 2, pointSum); // 这里是 i+2 此逻辑是因为加了"."需要多加一个1
                // 回溯
                pointSum--;
                s.erase(s.begin() + i + 1); // 删除"."
            } else {
                break;
            }
        }

看起来并不复杂,但是,难疑点比较多。首先就是先判断当前的这个切片处是否符合IP格式,然后再进行插入逗点,pointSum再做记录,然后就可以开始递归了,这里的是 i+2的,因为这个时候插入了逗点,所以需要后移一位,接着就是回溯了。

(4)主函数中存在一个小小的剪枝操作,如下:

if (s.size() < 4 || s.size() > 12) return result;

(5)判断是否为ip的函数为:

    bool isValud(string &s, int start, int end) {
        if (start > end) {
            return false;
        }
        // 头号字符不能为0(只有一位时可以)
        if (s[start] == '0' && start != end) {
            return false;
        }
        // 小于等于255
        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;
    }

这里的细节也比多:

1、start和end的比较;

2、头数字不为0,且不是只有一个数字;

3、和小于等于255;

2、整体代码如下:

class Solution {
private:
    // 判断是否为合法IP
    bool isValud(string &s, int start, int end) {
        if (start > end) {
            return false;
        }
        // 头号字符不能为0(只有一位时可以)
        if (s[start] == '0' && start != end) {
            return false;
        }
        // 小于等于255
        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;
    }

    vector<string> result;
    void backtracking(string &s, int startIndex, int pointSum) { 
        // pointsum是用来判断这个字符串中存在多少个"."如果有了三个,就说明满足IP格式了
        if (pointSum == 3) {
            if (isValud(s, startIndex, s.size() - 1)) {
            // 这里还有一个条件就是判断最后的一段是否符合IP要求
                result.push_back(s);
            }
            return;
        } 
        // 单层递归逻辑
        for (int i = startIndex; i < s.size(); i++) {
            if (isValud(s, startIndex, i)) {
                s.insert(s.begin() + i + 1, '.'); // 插入"."
                pointSum++;
                backtracking(s, i + 2, pointSum); // 这里是 i+2 此逻辑是因为加了"."需要多加一个1
                // 回溯
                pointSum--;
                s.erase(s.begin() + i + 1); // 删除"."
            } else {
                break;
            }
        }
    }
public:
    vector<string> restoreIpAddresses(string s) {
        if (s.size() < 4 || s.size() > 12) return result; // 算是剪枝了
        backtracking(s, 0 , 0);
        return result;
    }
};

 三、子集

1、思路:

(1)返回值和终止条件并没有什么改变:

void backtracking(vector<int> &nums, startIndex)

(2)终止条件(这个条件可有可不有,因为在return时以及到了叶子节点处,循环自然就不去了,就不用手动终止了):

if (startIndex >= nums.size()) return;

(3)单层递归逻辑:

for (int i = startIndex; i < nums.size(); i++) {
            // 插入元素
            path.push_back(nums[i]);
            // 递归
            backtracking(nums, i + 1);
            // 回溯
            path.pop_back();
        }

还是插入,递归,回溯。。。

(4)最重要的就是收集path,在每次递归开始时就可以收集子集了;

2、整体代码如下:

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& nums, int startIndex) {
        // 收集结果,每递归一次就可以收集一次结果
        result.push_back(path);
        // 终止条件,可写可不写,因为到了最后的叶子节点,自然会终止的
        if (startIndex >= nums.size()) return;

        for (int i = startIndex; i < nums.size(); i++) {
            // 插入元素
            path.push_back(nums[i]);
            // 递归
            backtracking(nums, i + 1);
            // 回溯
            path.pop_back();
        }
        return;
    }
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        backtracking(nums, 0);
        return result;
    }
};

 四、子集||

1、思路:

这个题目和上一题加上组合总和|||综合,这里也需要添加一个used来判断是否使用了这个元素,如果使用了那就可以继续遍历,说明在树枝上,但是如前面一个元素相同,但是没有被使用,说明在数层上面,就需要跳过这个数字了,避免重复。

图解如下:

 

 

这里就不一步步分析了;

2、整体代码如下:

class Solution {
private:
    vector<int> path;
    vector<vector<int>> result;
    void backtracking(vector<int>& nums, int startIndex, vector<bool> &used) {
        result.push_back(path);
        for (int i = startIndex; i < nums.size(); i++) {
            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
                continue;
            }
            path.push_back(nums[i]);
            used[i] = true;
            backtracking(nums, i + 1, used);
            used[i] = false;
            path.pop_back();
        }
        return;
    }
public:
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        vector<bool> used(nums.size(), false);
        sort(nums.begin(), nums.end());
        backtracking(nums, 0, used);
        return result;
    }
};

今日学习时间:2小时

leave message:

Her behavior is well-accorded with the expectations of her parents.

她的行为与父母的期望相符。 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1563872.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【BlossomConfig】SpringCloud项目是如何对bootstrap配置文件进行加载的?

文章目录 bootstrap配置文件的读取什么是配置中心&#xff1f;以及如何实现一个配置中心&#xff1f;SpringBoot如何实现配置的管控&#xff1f;SpringCloud项目是如何对bootstrap配置文件进行加载的&#xff1f;Nacos是如何实现配置文件的读取加载的&#xff1f;开发配置中心前…

2024年4月腾讯云最新活动:领3150元代金券礼包,新购、续费、升级可用!

腾讯云推出大促优惠活动&#xff1a;免费领取3150元代金券礼包&#xff1b;云服务器、云数据库、COS等上云必备产品&#xff0c;低至1.8折起&#xff1b;云产品助力企业和开发者轻松上云&#xff01; 活动入口&#xff1a;https://txy.ink/act/ 活动详情&#xff1a; 1、新人…

顺序表的创建

本期我们主要讨论动态顺序表 这个内容可以分为三个部分 1.创建头文件进行函数声明 2.创建源文件进行函数定义 3.创建主文件进行测试 我们先来看看头文件里的函数声明&#xff1a; 函数声明&#xff1a; 头文件中包括<stdlib.h>库函数用于进行动态内存管理&#xff0…

【攻防世界】warmup (代码审计)

进入题目环境&#xff0c;只有一个表情&#xff1a; ctrl u 查看源代码&#xff1a; 源代码提示我们访问 /source.php。访问结果如下&#xff1a; 我们进行代码审计&#xff0c;发现解题的关键点 include &_REQUEST[file]。但是题目使用了白名单进行了过滤。我们发现白名单…

C++bitset类型

bitset类型 我们介绍了将整型运算对象当作二进制位集合处理的一些内置运算符。 标准库还定义了bitset类&#xff0c;使得位运算的使用更为容易&#xff0c;并且能够处理超过最长整型类型大小的位集合。bitset类定义在头文件bitset中。 定义和初始化bitset bitset类是一个类模…

近屿智能独家发布行业领先的AIGC学习路径图

近日来“人工智能即将取代大量人类工作”的话题愈演愈烈&#xff0c;在CCTV-13的《两会你我他》访谈节目中&#xff0c;众多专家也围绕这一议题展开了深入的讨论&#xff0c;AI不会取代你的工作&#xff0c;会取代你的是懂AI技术的人。李强总理在访谈中也强调了推动"人工智…

【NTN 卫星通信】卫星辅助补充下行数据应用场景

1 卫星辅助下行数据场景概述 在乡村地区向地面接入网覆盖欠佳或无线电条件(例如山谷地区)的用户提供无线接入网可能无法提供所需的服务性能。   增加补充下行数据容量(例如由NTN提供)将有助改善服务性能和QoE&#xff0c;例如支援与视讯消费有关的流量不对称。因此&#xff0…

SpringBoot:自定义线程池配置类

文章目录 一、前言二、案例展示1、初始版本2、代码审核意见和优化建议3、潜在问题和风险4、优化建议5、优化后的代码 三、具体使用 一、前言 有时候我们在项目中做一些长链路的跑批任务时&#xff0c;基于Springboot项目的定时任务&#xff0c;我们可以指定一个自定义的线程配…

C-偶遇行军蚁(遇到过的题,做个笔记)

我的代码: 思路就是把每一行看成一个字符串&#xff0c;然后逐渐增加字符就行 #include <iostream> #include <vector> using namespace std; int main() {string s;int n;cin >> n; //读入行数cin >> s; //读入字符串vector<string>arr(n…

一起来从Solidworks中导出URDF模型

这个博客是用来记录关于【从Solidworks中导出URDF模型】的学习历程&#xff1a; 相关课程链接见&#xff1a;如何从Solidworks导出URDF模型 • 古月 (guyuehome.com) 下面让我们一起开始吧&#xff01;&#xff01;&#xff01; 1. sw_urdf_exporter插件介绍 插件下载链接&…

共享社会经济路径(SSP1-5)中国及分省人口预估数据库_v2

v1数据集&#xff1a; 在共享社会经济路径&#xff08;SSPs&#xff09;全球框架下&#xff0c;根据本地化人口和经济参数&#xff0c;采用人口-发展-环境&#xff08;PDE&#xff09;模型&#xff0c;构建2020-2100年SSPs人口格点数据&#xff1b;采用柯布-道格拉斯&#xff…

基于STM32的汽车防窒息系统

文章目录 基于STM32的汽车防窒息系统系统简介材料展示视频制作硬件连接原理图PCB实物图GSM模块使用GSM模块代码 SGP30模块SGP30模块代码 步进电机驱动步进电机代码 其他模块主逻辑代码 总结 基于STM32的汽车防窒息系统 系统简介 随着社会的发展目前汽车的流行&#xff0c;汽车大…

vSAN vs SmartX 超融合:BI 数仓跑批效率对比测试

在《VMware 与 SmartX 分布式存储缓存机制浅析与性能对比》中&#xff0c;我们分析了 vSAN 7 缓存击穿的问题及其原因。近期&#xff0c;某金融用户在进行数据仓库分布式存储选型时&#xff0c;同样遭遇了测试过程中 vSAN 出现缓存击穿而难以完成全量跑批任务的问题。随后&…

安卓Android 架构模式及UI布局设计

文章目录 一、Android UI 简介1.1 在手机UI设计中&#xff0c;坚持的原则是什么1.2 安卓中的架构模式1.2.1 MVC (Model-View-Controller)设计模式优缺点 1.2.2 MVP(Model-View-Presenter)设计模式MVP与MVC关系&#xff1a; 1.2.3 MVVM(Model—View—ViewModel ) 设计模式1.2.4 …

ssm018简易版营业厅宽带系统+jsp

营业厅宽带系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本营业厅宽带系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间…

群晖NAS使用Docker部署大语言模型Llama 2结合内网穿透实现公网访问本地GPT聊天服务

文章目录 1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址 随着ChatGPT 和open Sora 的热度剧增,大语言模型时代,开启了AI新篇章,大语言模型的应用非常广泛&#xff0c;包括聊天机…

新发现!科学家最新成果:补充类“原知因起源金”物质可延长寿命23%

近日&#xff0c;美哥伦比亚大学Vijay Yadav团队在《Science》发布了一项重磅级成果&#xff1a;通过补充一种特殊氨基酸&#xff08;带有磺酸基团的全能抗衰物质&#xff09;&#xff0c;竟然惊人地将实验动物的寿命延长了23%。 而其背后的机制&#xff0c;与早已火爆电商圈的…

Git命令(1)[删除,恢复与移动]

文章目录 1.删除文件1.1命令----rm <filename>1.2命令----git rm <filename>1.1命令----git rm <filename> -f 2.恢复文件2.1命令----git restore <filename>2.1命令----git restore --staged <filename> 3.重命名文件3.1命令----mv <oldFile…

javaweb学习(day10-服务器渲染技术)

一、基本介绍 1.前言 目前主流的技术是 前后端分离 (比如: Spring Boot Vue/React)JSP 技术使用在逐渐减少&#xff0c;但使用少和没有使用是两个意思&#xff0c;一些老项目和中小公司还在使用 JSP&#xff0c;工作期间&#xff0c;你很有可能遇到 JSPJSP 使用在减少(但是现…

分布式唯一ID 雪花算法

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 算法具体介绍 雪花算法是 64 位 的二进制&#xff0c;一共包含了四部分&#xff1a; 1位是符号位&#xff0c;也就是最高位&#xff0c;…