剑指 Offer II 087. 复原 IP

ops/2025/3/18 9:59:56/

comments: true
edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20087.%20%E5%A4%8D%E5%8E%9F%20IP/README.md

剑指 Offer II 087. 复原 IP

题目描述

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 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 地址。

 

示例 1:

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

示例 2:

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

示例 3:

输入:s = "1111"
输出:["1.1.1.1"]

示例 4:

输入:s = "010010"
输出:["0.10.0.10","0.100.1.0"]

示例 5:

输入:s = "10203040"
输出:["10.20.30.40","102.0.30.40","10.203.0.40"]

 

提示:

  • 0 <= s.length <= 3000
  • s 仅由数字组成

 

注意:本题与主站 93 题相同:https://leetcode.cn/problems/restore-ip-addresses/ 

解法

方法一:DFS

我们定义一个函数 d f s ( i ) dfs(i) dfs(i),表示从字符串 s s s 的第 i i i 位开始,搜索能够组成的 IP 地址列表。

函数 d f s ( i ) dfs(i) dfs(i) 的执行步骤如下:

如果 i i i 大于等于字符串 s s s 的长度,说明已经完成了四段 IP 地址的拼接,判断是否满足四段 IP 地址的要求,如果满足则将当前 I P IP IP 加入答案。

如果 i i i 小于字符串 s s s 的长度,此时还需要拼接 I P IP IP 地址的一段,此时需要确定这一段 I P IP IP 地址的值。如果该值大于 255 255 255,或者当前位置 i i i 0 0 0 i i i 之后的若干位的数值大于 0 0 0,则说明不满足要求,直接返回。否则,将其加入 I P IP IP 地址列表,并继续搜索下一段 I P IP IP 地址。

时间复杂度 O ( n × 3 4 ) O(n \times 3^4) O(n×34),空间复杂度 O ( n ) O(n) O(n)。其中 n n n 为字符串 s s s 的长度。

Python3
class Solution:def restoreIpAddresses(self, s: str) -> List[str]:def check(p):if p[0]=="0":return p=="0"return 0<int(p)<=255n=len(s)res=[]path=[]def dfs(i,j,times): # 枚举边界,以及已经分割添加的个数if times>=3 and len(s[i:])>3:returnif times==4 and not s[i:]:  #保证正好切分四个res.append(".".join(path[:]))return     for j in range(i,n):if check(s[i:j+1]) and times<4:path.append(s[i:j+1])dfs(j+1,j+1,times+1)path.pop()dfs(0,0,0)return res
Java
class Solution {private int n;private String s;private List<String> ans = new ArrayList<>();private List<String> t = new ArrayList<>();public List<String> restoreIpAddresses(String s) {n = s.length();this.s = s;dfs(0);return ans;}private void dfs(int i) {if (i >= n && t.size() == 4) {ans.add(String.join(".", t));return;}if (i >= n || t.size() >= 4) {return;}int x = 0;for (int j = i; j < Math.min(i + 3, n); ++j) {x = x * 10 + s.charAt(j) - '0';if (x > 255 || (s.charAt(i) == '0' && i != j)) {break;}t.add(s.substring(i, j + 1));dfs(j + 1);t.remove(t.size() - 1);}}
}
C++
class Solution {
public:vector<string> restoreIpAddresses(string s) {int n = s.size();vector<string> ans;vector<string> t;function<void(int)> dfs = [&](int i) {if (i >= n && t.size() == 4) {ans.push_back(t[0] + "." + t[1] + "." + t[2] + "." + t[3]);return;}if (i >= n || t.size() >= 4) {return;}int x = 0;for (int j = i; j < min(n, i + 3); ++j) {x = x * 10 + s[j] - '0';if (x > 255 || (j > i && s[i] == '0')) {break;}t.push_back(s.substr(i, j - i + 1));dfs(j + 1);t.pop_back();}};dfs(0);return ans;}
};
Go
func restoreIpAddresses(s string) (ans []string) {n := len(s)t := []string{}var dfs func(int)dfs = func(i int) {if i >= n && len(t) == 4 {ans = append(ans, strings.Join(t, "."))return}if i >= n || len(t) == 4 {return}x := 0for j := i; j < i+3 && j < n; j++ {x = x*10 + int(s[j]-'0')if x > 255 || (j > i && s[i] == '0') {break}t = append(t, s[i:j+1])dfs(j + 1)t = t[:len(t)-1]}}dfs(0)return
}
TypeScript
function restoreIpAddresses(s: string): string[] {const n = s.length;const ans: string[] = [];const t: string[] = [];const dfs = (i: number): void => {if (i >= n && t.length === 4) {ans.push(t.join('.'));return;}if (i >= n || t.length === 4) {return;}let x = 0;for (let j = i; j < i + 3 && j < n; ++j) {x = x * 10 + s[j].charCodeAt(0) - '0'.charCodeAt(0);if (x > 255 || (j > i && s[i] === '0')) {break;}t.push(x.toString());dfs(j + 1);t.pop();}};dfs(0);return ans;
}
C#
public class Solution {private IList<string> ans = new List<string>();private IList<string> t = new List<string>();private int n;private string s;public IList<string> RestoreIpAddresses(string s) {n = s.Length;this.s = s;dfs(0);return ans;}private void dfs(int i) {if (i >= n && t.Count == 4) {ans.Add(string.Join(".", t));return;}if (i >= n || t.Count == 4) {return;}int x = 0;for (int j = i; j < i + 3 && j < n; ++j) {x = x * 10 + (s[j] - '0');if (x > 255 || (j > i && s[i] == '0')) {break;}t.Add(x.ToString());dfs(j + 1);t.RemoveAt(t.Count - 1);}}
}
Swift
class Solution {private var n: Int = 0private var s: String = ""private var ans: [String] = []private var t: [String] = []func restoreIpAddresses(_ s: String) -> [String] {n = s.countself.s = sdfs(0)return ans}private func dfs(_ i: Int) {if i >= n && t.count == 4 {ans.append(t.joined(separator: "."))return}if i >= n || t.count >= 4 {return}var x = 0let chars = Array(s)for j in i..<min(i + 3, n) {x = x * 10 + Int(chars[j].wholeNumberValue!)if x > 255 || (chars[i] == "0" && i != j) {break}t.append(String(chars[i...j]))dfs(j + 1)t.removeLast()}}
}

http://www.ppmy.cn/ops/166736.html

相关文章

求职招聘网站源码,找工作招工系统,支持H5和各种小程序

招聘找活招工平台系统源码 招聘求职找工作软件 发布信息积分充值招聘系统,里面带纤细教程 功能介绍: 招工小程序主要针对工地招工工人找工作,工地可以发布招工信息,工人可以发布找活信息,招工信息可以置顶,置顶需要积分,积分可以通过签到、分享邀请好友、充值获取,后…

Flutter PopScope对于iOS设置canPop为false无效问题

这个问题应该出现很久了&#xff0c;之前的组件WillPopScope用的好好的&#xff0c;flutter做优化打算“软性”处理禁用返回手势&#xff0c;出了PopScope&#xff0c;这个组件也能处理在安卓设备上的左滑返回事件。但是iOS上面左滑返回手势禁用&#xff0c;一直无效。 当然之…

人工智能之数学基础:从线性变换理解矩阵范数和矩阵行列式

本文重点 我们已经学习了线性变换了,而且我们知道每一个线性变换都有一个矩阵,那么本文我们从线性变换的角度来理解矩阵范数和行列式。 矩阵范数 为什么要学习范数呢?因为范数是程度概念的推广,在矩阵理论的计算方法中,要讨论收敛问题和逼近问题,那么就需要引入向量和…

【redis】Jedis 操作 Redis 基础指令(下)

列表操作 lpush/rpush 和 lpop/rpop 将一个或者多个元素从左/右侧放入&#xff08;头/尾插&#xff09;到 list 中 依次头插 从 list 左/右侧取出元素&#xff08;即头/尾删&#xff09; public static void test1(Jedis jedis) { jedis.flushAll(); long n jedis.lpush(…

9种Python数据可视化方案,让财务数据焕发生命力

想象一下&#xff1a;你即将向董事会展示季度财务报告&#xff0c;面对的是一群已经看过无数PPT的高管。你是选择用普通的柱状图和折线图&#xff0c;还是用能够直观展示收入、支出、利润动态关系的交互式仪表板&#xff1f; 本文将通过一个完整的Python财务数据可视化案例&am…

使用 yum 命令安装 MariaDB 指南

文章目录 前言为什么开始选择 MariaDB&#xff1f;安装 MariaDB安装mariadb-server启动服务初始化配置设置开机启动配置远程访问权限 总结个人简介 前言 最近在 CentOS 7 上安装 MySQL 后启动遇到如下错误&#xff1a; systemctl start mysqldFailed to start mysqld.service…

C语言内存函数讲解

&#xff08;一&#xff09;memcpy函数 这是memcpy函数的说明。它的头文件是string.h。函数原型是 void* memcpy(void* destination, const void* source, size_t num) 第一个参数是一个指向一个字符串的指针&#xff0c;第二个也是一样的。而第三个参数是复制的字节个数。这…

使用kubeadm方式以及使用第三方工具sealos搭建K8S集群

目录 kubeadm方式: 一、安装要求 二、环境准备 二、安装Docker、kubeadm、kubelet 1、安装Docker &#xff08;1&#xff09;首先配置一下Docker的阿里yum源 &#xff08;2&#xff09;然后用yum 方式安装docker &#xff08;3&#xff09;配置Docker镜像加速器 &#…