算法力扣刷题记录 七十二【93.复原IP地址】

news2024/9/21 0:51:48

前言

本文练习回溯章节。回溯章节第七篇。

记录 七十二【93.复原IP地址】。


一、题目阅读

有效 IP 地址 正好由四个整数每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。

例如:“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是 无效 IP 地址。
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 ‘.’ 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

示例 1:

输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]

示例 2:

输入:s = "0000"
输出:["0.0.0.0"]

示例 3:

输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]

提示:

1 <= s.length <= 20
s 仅由数字组成

二、尝试实现

分析题目

  1. 需要从题目分析应该用什么方法。不应该直接以章节来确定方法。
  2. 题目说给一个只包含数字的字符串s,所以无效ip地址中有@符号一类的已经被排除掉。输出结果是该字符串可能表达的ip地址:不让重新排序和删除,相当于在字符串中划分出四部分,插入三个’.'。在一个集合中切割问题,应该用回溯算法解决。

回溯3步曲

  1. 确定递归的返回值:用vector< string>& result作为参数存放结果,所以不需要返回值。void类型。
  2. 确定递归的参数:
  • const string& s表示传入的字符串,用const修饰以防被修改。
  • vector< string>& result用来放最后的返回值,引用形式;
  • string temp用来放中间分割的结果。不用引用了,值传递,传递副本。
  • int startindex表示下一层从哪个字符所在下标的后面开始分割。
  • int& depth表示第几层,因为ip地址是4个整数,所以到depth == 4时就应该判断有没有分割完成
  1. 确定终止条件:如果startindex == s.size()说明已经分割整个字符串,并且判断此时depth == 4说明分成了4个整数。如果depth不是4或者没有分割整个字符串都不满足ip地址
  • if(startindex == s.size() && depth == 4)
  1. 确定单层逻辑:
  • for循环应该从startindex 开始,到s.size()结束。i++.
  • for循环内部:
    • 首先根据 i 和startindex分割出子串str。用substr成员函数。
    • 得到子串后判断这个子串是否在[0,255]并且前导不为0。(这部分逻辑在第5条说)
    • depth++。代表分割的数字多了一个;
    • 把子串str放到temp中。不过需要加’.',所以有个判断:if(depth > 1)说明不是第一个整数,后面的整数加到temp之前先加‘.’。
    • 递到下一层:startindex传入i+1.
    • 回溯:temp.earse掉子串str;如果temp不是空,还要pop,去掉’.';depth–。(3个回溯)
  1. 得到子串后判断这个子串是否在[0,255]并且前导不为0。
  • 首先把子串str转换成int类型。但是发现int类型不够,整数会超出int范围,所以改成long long类型;但是提交后又发现用例还能超出long long类型;所以第一步应该先判断如果str.size() > 3,直接continue。
  • 把子串str用stoi函数转换成int类型;
  • 范围判断:if(num < 0 || num > 255) continue;
  • 前导’0’判断:if(str.size() > 1 && str[0] == ‘0’) continue;
  1. 总结:需要解决以下问题,才完整做出题目——
  • 如何控制分割出来的是4个子串并且分割完整的字符串?(终止条件)
  • 如何判断整数符合ip条件?(注意范围控制)
  • 如何回溯?不要少任何一个变量的回溯
  • 如何处理’.'?

代码实现

class Solution {
public:
    void backtracking (const string& s,int startindex,int& depth,string temp,vector<string>& result ){
        if(startindex == s.size() && depth == 4){
            result.push_back(temp);
            return;
        }

        for(int i = startindex;i < s.size();i++){
            string str = s.substr(startindex,i-startindex+1);
            //判断子串符不符合ip要求
            if(str.size() > 3) continue;
            int num = stoi(str);//这种转变不能覆盖整个用例。
            if(num < 0 || num > 255){//整数不在0-255.
                continue;
            }
            if(str.size() > 1 && str[0] == '0'){//前导0,也不行
                continue;
            }
            //以下是符合整数的
            depth ++;
            if(depth > 1){
                temp += '.';
            }
            temp += str;
            backtracking(s,i+1,depth,temp,result);
            //回溯
            temp.erase(temp.size()-str.size(),str.size());//位置和长度.删去放入的str
            if(!temp.empty()){
                temp.pop_back();//弹出'.'
            }
            depth--;
        }
        return;
    }
    vector<string> restoreIpAddresses(string s) {
        vector<string> result;
        string temp;//可能的结果
        int depth = 0;
        backtracking(s,0,depth,temp,result);
        return result;
    }
};

三、参考学习

【93.复原IP地址】参考学习链接

学习内容

  1. 分割问题类似组合问题要用到回溯。需要解决的问题依然是以上总结出来的,但是参考给的方法有所区别:
  • 区别一:直接在原有字符串s中加’.',不需要temp;
  • 区别二:因为直接在原有字符串s中加’.‘,所以计数’.'的数量pointnum。
  • 区别三:把判断子串合法性另写一个函数。
  1. 所以根据参考给的思路重新实现:
class Solution {
public:
    //判断子串是否合法,输入起始下标和终止下标。左闭右闭区间。
    bool isvalid(string s,int start,int end){
        //前导存在0.
        if((end-start+1) > 1 && s[start] == '0') return false;
        //范围
        if((end-start+1) >= 1 && (end-start+1) <= 3){
            string sub = s.substr(start,end-start+1);
            int subnum = stoi(sub);
            if(subnum >=0 && subnum <= 255) return true;
        }
        return false;
    }
    void backtracking(string s,int pointnum,int startindex,vector<string>& result){
        //终止条件
        if(pointnum == 3){//说明已经插入了三个'.'
            //仍然需要判断最后一个整数
            if(isvalid(s,startindex,s.size()-1)){//最后一个整数区间:[startindex,s.end()-1]
                result.push_back(s);
                return;
            }
        }

        for(int i = startindex;i < s.size();i++){
            if(isvalid(s,startindex,i)){
                //第一步插入'.'
                s.insert(s.begin()+i+1,'.');//insert在第一个参数所指位置之前插入'.'
                //数量+1
                pointnum++;
                backtracking(s,pointnum,i+2,result);//递到下一层,注意已经插入了'.'
                //回溯
                s.erase(s.begin()+i+1);//所指位置删除
                pointnum--;
            }else break;//这从参考中学到。
        }
        return;
    }
    vector<string> restoreIpAddresses(string s) {
        vector<string> result;
        backtracking(s,0,0,result);
        return result;
    }
};
  • 在for循环的 最后else break。在本题的用例中,如果不合法,就是整数已经是4位了,所以后面无需遍历,可以直接跳出,不用再isvalid执行,效率更高。
  • 对比参考的isvalid函数:参考的函数在num获取中判断了非法字符。
bool isValid(const string& s, int start, int end) {
        if (start > end) {
            return false;
        }
        if (s[start] == '0' && start != end) { // 0开头的数字不合法
                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) { // 如果大于255了不合法
                return false;
            }
        }
        return true;
    }

总结

在这里插入图片描述
(欢迎指正,转载标明出处)

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

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

相关文章

前端面试题整合

一、HTML篇 1、简述一下你对HTML语义化的理解&#xff1f; 用正确的标签做正确的事情&#xff1b; HTML语义化让页面内容结构清晰&#xff0c;便于浏览器、搜索引擎解析&#xff1b; 搜索引擎的爬虫依赖HTML标记来确定上下文和关键字的权重&#xff0c;利于SEO&#xff1b; 便于…

Typro + PicGo 图床 + Docsify + GitHub Pages,玩转个人知识库搭建,写给小白的建站入门课

自动开了这个号以后&#xff0c;陆陆续续写了很多干货文章&#xff0c;一方面是可以帮助自己梳理思路&#xff0c;另一方面也方便日后查找相关内容。 但是&#xff0c;我想检索某个关键词是在之前哪篇文章写过的&#xff0c;就有点捉急了。CSDN 还好&#xff0c;可以检索到相关…

趋动科技陈飞:从小模型到大模型,AI时代下的数据中心建设

自AI大模型横空出世&#xff0c;不断推动着AI从学术界到产业界向大众破圈&#xff0c;新的时代正在来临。11月15-16日&#xff0c;由CDCC主办的“2023第11届数据中心标准大会”在北京国家会议中心盛大开幕。 本届大会的主题围绕“AI时代 重塑未来”&#xff0c;聚焦数据中心领…

pycharm使用fastapi/uvicorn无法reload的问题

pycharm使用fastapi/uvicorn无法reload的问题 一、前言 1、解决方法 &#xff08;1&#xff09;控制台执行uvicorn指令 pycharm的问题&#xff0c;建议控制台直接输uvicorn main:app --reload&#xff0c;而不是在代码里 uvicorn.run() 运行 &#xff08;2&#xff09;将uv…

sharded_inference_engine:MLXDynamicShardInferenceEngine;step

目录 sharded_inference_engine:MLXDynamicShardInferenceEngine 类属性 方法 __init__(self) async def infer_prompt(self, shard: Shard, prompt: str, inference_state: Optional[str] = None) -> (np.ndarray, str, bool) async def infer_tensor(self, shard: …

小白零基础学数学建模系列-Day1-数学建模入门介绍

目录 第1天&#xff1a;数学建模入门介绍一、介绍数学建模的定义和重要性二、常见的数学建模方法概述三、确定问题和建立假设四、模型构建步骤及求解模型的方法五、模型的验证与检验的必要性 作业作业案例分析&#xff1a;实际问题&#xff1a;城市交通拥堵预测问题描述建模方案…

【大模型学习】多模态大模型进行偏好优化

一、简介 训练模型以理解并预测人类偏好是一项复杂的任务。传统方法如SFT&#xff08;监督微调&#xff09;通常需要较高的成本&#xff0c;因为这些算法需要对数据进行特定标签的标注。偏好优化&#xff08;Preference Optimization&#xff09;作为一种替代方案&#xff0c;…

云计算任务调度优化matlab仿真,对比蚁群优化和蛙跳优化

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 ACO蚁群优化 4.2 蛙跳优化 5.完整程序 1.程序功能描述 云计算任务调度优化,优化目标位任务消耗时间&#xff0c;调度后的经济效益以及设备功耗&#xff0c;对比蚁群优化算法和蛙跳优化…

【IEEE独立出版 | EI稳定检索】第三届人工智能、物联网和云计算技术国际会议(AIoTC 2024)

【IEEE独立出版 | EI稳定检索】 第三届人工智能、物联网和云计算技术国际会议&#xff08;AIoTC 2024&#xff09; 2024 3rd International Conference on Artificial Intelligence, Internet of Things and Cloud Computing Technology 2024年9月13-15日 | 中国武汉 AIoTC …

mysql 日志爆满,删除日志文件,定时清理日志

今天发现网站不能正常访问&#xff0c;于是登陆服务器查找问题。 机智的我随手用命令&#xff1a;df -l 发现 硬盘爆满了&#xff0c;于是就知道问题所在了。 Filesystem 1K-blocks Used Available Use% Mounted on/dev/xvda1 20641404 16963004 16929876 10…

使用 Elastic 和 Mistral 构建多语言 RAG(二)

这篇文章是之前的文章 “使用 Elastic 和 Mistral 构建多语言 RAG&#xff08;一&#xff09;” 的续篇。在这篇文章中&#xff0c;我将展示如何在本地部署中完成在那篇文章中的实现。 注意&#xff1a;由于 semantic text 从 8.15 版本开始提供&#xff0c;你需要至少 8.15 及…

Go框架选战:Gin、Echo、Fiber的终极较量

Gin 优点: 高性能: 优化以处理高并发和低延迟请求。易于上手: 对于熟悉 Go 的开发者来说&#xff0c;API 设计直观&#xff0c;学习曲线低。社区支持强: 广泛使用&#xff0c;有大量第三方中间件和教程。 缺点: 相比于其他框架如 Echo&#xff0c;Gin缺乏内置的验证支持Gin…

万字长文揭秘高性能架构

从零开始学架构系列文章&#xff1a; 从零开始学架构——概念和基础 从零开始学架构——万字长文揭秘高性能架构 从零开始学架构——高可用架构 从零开始学架构——可扩展架构 高性能存储 关系数据库 互联网业务兴起之后&#xff0c;海量用户加上海量数据的特点&#xff0…

无人机之民用无人机用途分类篇

一、航拍无人机 用于航拍摄影和电影制作&#xff0c;提供空中视角的拍摄服务。可用于电影制作、广告拍摄、房地产销售等。 二、物流无人机 用于快递和货物运输&#xff0c;提高物流效率&#xff0c;可以到达传统配送方式难以覆盖的地区&#xff0c;在突发事件如自然灾害、疫…

keepalived工作原理和使用方式

keepalived是什么 keepalived是集群管理中保证集群高可用的一个服务软件&#xff0c;用来防止单点故障。 keepalived主要有三个模块 分别是core、check和vrrp。core模块为keepalived的核心&#xff0c;负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检…

怎么根据企业特点提供个性化的六西格玛培训?

近年来&#xff0c;六西格玛作为一种强大的质量管理方法&#xff0c;以其数据驱动、流程优化和减少缺陷为核心&#xff0c;被众多企业视为提升竞争力的关键工具。然而&#xff0c;并非所有企业都能直接套用标准的六西格玛培训体系&#xff0c;因为每个企业的文化、行业特性、发…

顺序队列和链式队列的基本操作

顺序队列 函数说明&#x1f603;&#xff1a; InitStack( &s)&#xff1a;初始化栈 StackEmpty(s)&#xff1a;判断一个栈是否为空 Push(& s, x)&#xff1a;进栈 Pop(&s, &x)&#xff1a;出栈 GetTop(s,&x)&#xff1a;读栈顶元素 show(s)&#xff1a;读出…

Vue3项目框架搭建

前言 大多时候是在别人搭建好的项目上开发需求&#xff0c;突然要自己从新项目搭建开始&#xff0c;纯纯赶鸭子上架&#xff0c;参考一些项目&#xff0c;试着搭建的&#xff0c;记录一下历程&#xff0c;主要怕忘了。有些地方本该贴上代码截图更好&#xff0c;但是我此刻手头…

Vue引入使用iconfont字体图标

由于element-ui或element-plus提供的图标有时候并不能满足日常需求,所以这篇介绍一下前端引入阿里巴巴矢量图标库使用,不止是vue使用,不限于vue2、vue3,html或是其他框架也是同样的道理,只要引入都是同样可以使用的。 1. 首先进入阿里巴巴矢量图标库官网 官网:https://…

弱智吧:大模型变聪明,有我一份贡献【大模型VS弱智吧,谁聪明?谁弱智?】

「被门夹过的核桃&#xff0c;还能补脑吗&#xff1f;」 在中文网络上流传着这样一段话&#xff1a;弱智吧里没有弱智。 百度「弱智吧」是个神奇的地方&#xff0c;在这里人人都说自己是弱智&#xff0c;但大多聪明得有点过了头。最近几年&#xff0c;弱智吧的年度总结文章都可…