leetCode 93.复原 IP 地址 + 回溯算法 + 图解 + 笔记

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


有效 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"]

题目要求:给我们个字符串,切割成一个合法的IP地址(IPv4形式)

思路和分析(O_O)?  

  • 切割问题可以使用回溯搜索法把所有可能性搜出来
  • 切割问题可以抽象树形结构
  • 判断子串是否合法

(一)判断子串是否合法,主要考虑三点: 

  • 1)以0开头的数字不合法
if(s[start] == '0' && start != end) { // 0开头的数字不合法return false;
}
  • 2)有非正整数字符不合法
if(s[i]>'9' || s[i]<'0') { // 遇到非数字字符不合法return false;
}
  • 3)如果大于255不合法
if(num > 255) return false;// 如果大于255了,不合法
// 判断字符串s在左闭右闭区间[start,end]所组成的数字是否合法
bool isValid(const string& s,int start,int end) {if(start > end) return false;if(s[start] == '0' && start != end) { // 0开头的数字不合法return false;}// num = num*10+(s[i]-'0');// "225" -> 2*10=20 //          20*10+2=22 //          22*10+5=225int 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;// 如果大于255了,不合法}return true;
}

(二)回溯三部曲:

1.确定递归参数返回类型

  • startIndex:记录搜索的起始位置,是下一次递归分割的起始位置,可确保不会重复分割
  • pointNum:记录添加逗点的数量
void backtracking(string& s,int startIndex,int pointNum)

2.确定递归终止条件

  • leetCode 131.分割回文串是以切割线到最后作为终止条件
  • 本题是 IPv4 地址,故所给字符串会被分成 4段,所以以分割的段数作为终止条件
  • 如果最后一段,也就是第四段字符串合法,才加入结果集result
if(pointNum == 3) { // 逗点数量为3时,分隔结束// 判断第四段字符串是否合法,如果合法就放进result中if(isValid(s,startIndex,s.size()-1)) {result.push_back(s);}return;
}

3.单层搜索的逻辑

[startIndex, i] 这个区间可用来截取的子串,接着判断这个子串是否合法

  • 1)如果合法,则在其后加上符号'.' 来表示已经分割
  • 2)如果不合法直接结束本层循环,在图中表现为剪掉分支

递归和回溯的过程:

  • 递归调用时,下一层递归的 startIndex 要从 i + 2 开始(在字符串中加入分隔符'.'),还有pointNum++,表示分隔符的数量增加一个;
  • 回溯时,将刚刚加入的分隔符 . 删掉就行,还有 pointNum--
for(int i=startIndex;i<s.size();i++) {if(isValid(s,startIndex,i)){     // 判断 [startIndex,i] 这个区间的子串是否合法s.insert(s.begin()+i+1,'.'); // 在i的后面插入一个逗点pointNum++;backtracking(s,i+2,pointNum);// 插入逗点之后下一个子串的起始位置为i+2pointNum--;                  // 回溯s.erase(s.begin()+i+1);      // 回溯删掉逗点}else break;                     //不合法,直接结束本层for循环
}

C++代码:

/*切割问题可以使用回溯搜索法把所有可能性搜出来切割问题可以抽象为树形结构判断子串是否合法,主要考虑三点:1).以0为开头的数字不合法2).有非正整数字符不合法3).如果大于255了不合法回溯三部曲:1.确定递归参数和返回类型startIndex:记录搜索的起始位置,是下一次递归分割的起始位置,可确保不会重复分割pointNum:记录添加逗点的数量2.确定递归终止条件- leetCode 131.分割回文串是以切割线到最后作为终止条件- 本题是IPv4地址,故所给字符串会被分成4段,所以以分割的段数作为终止条件3.单层搜索的逻辑[startIndex, i] 这个区间可用来截取的子串,接着判断这个子串是否合法1).如果合法,则在其后加上符号'.' 来表示已经分割2).如果不合法就直接结束本层循环,在图中表现为剪掉分支递归和回溯的过程:递归调用时,下一层递归的startIndex要从 i + 2开始(在字符串中加入分隔符.),还有pointNum++,表示分隔符的数量增加一个回溯时,将刚刚加入的分隔符 . 删掉就行,还有pointNum--*/  
class Solution {
public:vector<string>result;// 记录结果// 判断字符串s在左闭右闭区间[start,end]所组成的数字是否合法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) return false;// 如果大于255了,不合法}return true;}void backtracking(string& s,int startIndex,int pointNum) {if(pointNum == 3) { // 逗点数量为3时,分隔结束// 判断第四段字符串是否合法,如果合法就放进result中if(isValid(s,startIndex,s.size()-1)) {result.push_back(s);}return;}for(int i=startIndex;i<s.size();i++) {if(isValid(s,startIndex,i)){     // 判断 [startIndex,i] 这个区间的子串是否合法s.insert(s.begin()+i+1,'.'); // 在i的后面插入一个逗点pointNum++;backtracking(s,i+2,pointNum);// 插入逗点之后下一个子串的起始位置为i+2pointNum--;                  // 回溯s.erase(s.begin()+i+1);      // 回溯删掉逗点}else break;                     //不合法,直接结束本层for循环}}vector<string> restoreIpAddresses(string s) {if(s.size() < 4 || s.size() > 12) return result; // 算是剪枝了backtracking(s,0,0);return result;}
};

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

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

相关文章

CS 2520nonono

CS 2520nonono WeChat&#xff1a;yj4399_​​​​​ Sina Visitor System High-level●3 Congestion Control Algorithms:○TCP Reno:■additive increase, multiplicative decrease function to adjust window size for every RTTuntil a packet loss is detected○TCP CUBI…

编程的重要性及解决技术难题的方法

看到这个话题之后&#xff0c;出于好奇&#xff0c;使用某chat&#xff0c;输入相应主题得到的一篇文章&#xff0c;分享给大家。 PS&#xff1a;现在不同版本的chat和其快速更新升级也可以说是编程的结果&#xff0c;其重要性和发展历程也反映了编程的重要性。 一、编程的重要…

关于java agent

关于java agent技术,可以看看这个文章, 聊聊JavaAgent - 知乎

详解ClickHouse的ReplaceMergeTree

区别于MergeTree表引擎&#xff0c;ReplacingMergeTree删除重复数据时是通过相同的分区值&#xff08;ORDER BY的值&#xff09; 数据去重发生在后台合并数据时&#xff0c;后台合并数据是随机的&#xff0c;所以有时会有一些没处理的数据&#xff0c;可以通过OPTIMIZI来手动合…

python-元组和列表的异同

Python中的元组&#xff08;Tuple&#xff09;和列表&#xff08;List&#xff09;都是用于存储多个元素的数据结构&#xff0c;但它们有一些关键的区别。 相同点&#xff1a; 存储多个元素&#xff1a; 元组和列表都可以用来存储多个元素。 可迭代&#xff1a; 两者都支持迭…

用java实现拼图小游戏

1、了解拼图游戏基本功能&#xff1a; 拼图游戏内容由若干小图像块组成的&#xff0c;通过鼠标点击图像块上下左右移动&#xff0c;完成图像的拼凑。 2、拼图游戏交互界面设计与开发&#xff1a; 通过创建窗体类、菜单、中间面板和左右面板完成设计拼图的交互界面 &#xff…

分享从零开始学习网络设备配置--任务4.3 使用动态路由RIPng实现网络连通

任务描述 某公司使用IPv6技术搭建企业网络&#xff0c;由于静态路由需要管理员手工配置&#xff0c;在网络拓扑发生变化时&#xff0c;也不会自动生成新的路由&#xff0c;因此采用IPv6动态路由协议RIPng实现网络连通&#xff0c;实现任意两个节点之间的通信&#xff0c;并降低…

基于SpringBoot学生读书笔记共享

摘 要 本论文主要论述了如何使用JAVA语言开发一个读书笔记共享平台 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述读书笔记共享平台的当前背景以及系统开发的…

Python 2进制按位取反

根据一checksum算法需要将一些参数按位取反 例&#xff1a;参数 13 数字13二进制为1101 [((x)) for x in str(bin(13))] [0, b, 1, 1, 0, 1] 除去0b字符串然后按位取反得到0010 [(1^int(x)) for x in str(bin(13)).replace(0b,)] [0, 0, 1, 0]然后将得到的2进制转换成十进制…

第16关 革新云计算:如何利用弹性容器与托管K8S实现极速服务POD扩缩容

------> 课程视频同步分享在今日头条和B站 天下武功&#xff0c;唯快不破&#xff01; 大家好&#xff0c;我是博哥爱运维。这节课给大家讲下云平台的弹性容器实例怎么结合其托管K8S&#xff0c;使用混合服务架构&#xff0c;带来极致扩缩容快感。 下面是全球主流云平台弹…

第一百八十四回 自定义Radio组件

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法3. 代码与效果3.1 示例代码3.2 运行效果4. 内容总结我们在上一章回中介绍了"如何给图片添加阴影"相关的内容,本章回中将介绍 自定义Radio组件.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

对抗产品团队中的认知偏误:给产品经理的专家建议

今天的产品经理面临着独特的挑战。他们不仅需要设计和构建创新功能&#xff0c;还必须了解这些功能将如何为客户带来价值并推进关键业务目标。如果不加以控制&#xff0c;认知偏差可能会导致您构建的内容与客户想要的内容或业务需求之间不一致。本文将详细阐述产品经理可以避免…

下载MySQL JDBC驱动的方法

说明 java代码通过JDBC访问MySQL数据库&#xff0c;需要MySQL JDBC驱动。 例如&#xff0c;下面这段代码&#xff0c;因为找不到JDBC驱动&#xff0c;所以执行会报异常&#xff1a; package com.thb;public class JDBCDemo {public static void main(String[] args) throws …

【传智杯】排排队、小卡与质数 2、1024 程序员节发橙子题解

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; 蓝桥杯 &#x1f319;请不要相信胜利就像山坡上的蒲公英一样唾手…

网络基础_1

目录 网络基础 协议 协议分层 OSI七层模型 网络传输的基本流程 数据包的封装和分用 IP地址和MAC地址 网络基础 网络就是不同的计算机之间可以进行通信&#xff0c;前面我们学了同一台计算机之间通信&#xff0c;其中有进程间通信&#xff0c;前面学过的有管道&#xff…

Redis之秒杀系统

目录 Redis 秒杀 Mysql数据库设计 Mysql秒杀实现 MysqlRedis秒杀实现 秒杀是一种高并发场景&#xff0c;通常指的是在短时间内&#xff08;秒级别&#xff09;有大量用户同时访问某个商品或服务&#xff0c;争相抢购的情景。在这种情况下&#xff0c;系统需要处理大量并发请…

LSTM seq2seq 模型之英语到法语翻译

1. 数据集下载 Machine-Translation-eng-fra | Kaggle 2. 预处理的完整的代码 import os.pathimport numpy as np import tensorflow as tf import keras from keras.callbacks import EarlyStopping, ModelCheckpoint from keras.preprocessing.text import Tokenizer from …

Openai通用特定领域的智能语音小助手

无穷尽的Q&A 钉钉...钉钉... 双双同学刚到工位,报销答疑群的消息就万马纷沓而来。她只能咧嘴无奈的摇摇头。水都还没有喝一口就开始“人工智能”的去回复。原本很阳光心情开始蒙上一层薄薄阴影。在这无休无止的Q&A中&#xff0c;就算你对工作有磐石一般强硬&#xff0…

Linux C/C++高级全栈开发(后端/游戏/嵌入式/高性能网络/存储/基础架构)

Linux C/C高级全栈开发是一个涉及到多个领域的综合性技术要求&#xff0c;需要对Linux系统、C/C编程语言以及各种相关的技术进行深入的理解和应用。 下面是一些涵盖的主要技术领域和技能要点&#xff1a; Linux系统基础&#xff1a;熟悉Linux操作系统的原理和常用命令&#xf…

Linux下的文件IO之系统IO

1. 知识点 读入写出&#xff0c;切记以我们程序为中心向文件或者别的什么东西读入写出&#xff08;输入流输出流&#xff09; 人话就是 文件向我们程序就是读入 程序向文件或者别的什么就是写出 2. open打开文件 open.c /****************************************************…