当前位置: 首页 > news >正文

每日一题——将数字字符串转化为IP地址

将数字字符串转化为IP地址

    • 题目描述
    • 解题思路
      • 回溯法
      • 步骤分解
    • 代码实现
      • 全局变量
      • 有效性验证函数
      • 回溯函数
      • 主函数
      • 完整代码
    • 复杂度分析
    • 关键点说明
    • 总结

这题难度还挺大的,整体上实现并不容易。建议参考视频
和https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html#%E6%80%9D%E8%B7%AF

题目描述

给定一个仅包含数字的字符串,将其转换为所有可能的有效IP地址形式。有效的IP地址由四个整数(0到255之间)构成,各部分用.分隔,且不能有前导零(除非该段本身为0)。

示例

  • 输入:"25525522135"
    输出:["255.255.22.135", "255.255.221.35"]

  • 输入:"000256"
    输出:[](因256超过255)

解题思路

回溯法

  1. 分割逻辑:IP地址由四段组成,需在字符串中找到三个分割点将字符串分为四段。
  2. 有效性检查:每段必须满足:
    • 值在0255之间;
    • 无前导零(除非段本身为0);
    • 仅包含数字。
  3. 递归终止条件:当分割点数量为3时,检查最后一段是否有效。
  4. 剪枝:若当前分割无效,跳过后续尝试。

步骤分解

  1. 回溯函数:记录当前分割点位置和已分割段数。
  2. 有效性验证:检查子串是否合法。
  3. 生成结果:将合法分割组合成IP地址格式。
    在这里插入图片描述

代码实现

全局变量

char** result;      // 存储结果数组
int resultTop;       // 结果数组当前索引
int segments[3];     // 记录三个分割点的位置

有效性验证函数

int isValid(char* s, int start, int end) {if (start > end) return 0;if (s[start] == '0' && start != end) return 0; // 前导零无效int num = 0;for (int i = start; i <= end; i++) {if (s[i] < '0' || s[i] > '9') return 0;   // 非数字字符num = num * 10 + (s[i] - '0');if (num > 255) return 0;                  // 超过255}return 1;
}

回溯函数

void backTracking(char* s, int startIndex, int pointNum) {if (pointNum == 3) { // 分割点已满3个// 检查最后一段是否有效if (isValid(s, startIndex, strlen(s) - 1)) {char* temp = (char*)malloc(strlen(s) + 4); // 分配新字符串内存int count = 0, count1 = 0;for (int j = 0; j < strlen(s); j++) {temp[count++] = s[j];// 在分割点后插入'.'if (count1 < 3 && j == segments[count1]) {temp[count++] = '.';count1++;}}temp[count] = '\0';// 扩展结果数组并保存result = (char**)realloc(result, sizeof(char*) * (resultTop + 1));result[resultTop++] = temp;}return;}for (int i = startIndex; i < strlen(s); i++) {if (isValid(s, startIndex, i)) { // 当前分割有效segments[pointNum] = i;      // 记录分割点backTracking(s, i + 1, pointNum + 1); // 递归下一段} else break; // 无效分割,剪枝}
}

主函数

char** restoreIpAddresses(char* s, int* returnSize) {result = (char**)malloc(0);resultTop = 0;backTracking(s, 0, 0);*returnSize = resultTop;return result;
}

完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>char** result;  // 用于存储所有可能的IP地址
int resultTop;  // 当前result数组中的IP地址数量
// 记录应该加入'.'的位置,数组大小为3,因为IP地址有3个分隔点
int segments[3];// 检查字符串是否为合法的IP段
// start和end分别表示当前检查的子字符串的起始和结束位置
int isValid(char* s, int start, int end) {// 如果起始位置大于结束位置,说明子字符串无效if (start > end) {return 0;}// 如果子字符串以0开头且长度大于1,则该子字符串无效(例如01、001等)if (s[start] == '0' && start != end) {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');  // 将字符转换为数字并累加// 如果数字大于255,则子字符串无效if (num > 255) {return false;}}return true;  // 如果通过所有检查,则子字符串有效
}// 回溯函数,用于生成所有可能的IP地址
// startIndex表示当前处理的字符串起始位置,pointNum表示当前已放置的'.'数量
void backTracking(char* s, int startIndex, int pointNum) {// 如果已放置3个'.',说明已经生成了一个完整的IP地址if (pointNum == 3) {// 检查最后一段字符串是否合法if (isValid(s, startIndex, strlen(s) - 1)) {// 为存储当前IP地址分配内存char* tempString = (char*)malloc(sizeof(char) * (strlen(s) + 4));int count = 0;  // 用于记录tempString的当前索引int count1 = 0; // 用于记录已使用的'.'数量// 遍历字符串,根据segments数组插入'.'生成IP地址for (int j = 0; j < strlen(s); j++) {tempString[count++] = s[j];  // 将当前字符添加到tempString// 如果当前索引是'.'的位置,则插入'.'(最多插入3个)if (count1 < 3 && j == segments[count1]) {tempString[count++] = '.';count1++;}}tempString[count] = '\0';  // 添加字符串结束符// 扩容result数组以存储新的IP地址result = (char**)realloc(result, sizeof(char*) * (resultTop + 1));result[resultTop++] = tempString;  // 将新生成的IP地址加入result}return;}// 遍历字符串,尝试将当前子字符串作为IP地址的一部分for (int i = startIndex; i < strlen(s); i++) {// 检查当前子字符串是否合法if (isValid(s, startIndex, i)) {// 记录当前'.'的位置segments[pointNum] = i;// 递归处理下一段字符串backTracking(s, i + 1, pointNum + 1);} else {// 如果当前子字符串不合法,则停止当前分支的搜索break;}}
}// 主函数,用于恢复IP地址
char** restoreIpAddresses(char* s, int* returnSize) {// 初始化result数组result = (char**)malloc(0);resultTop = 0;// 开始回溯搜索backTracking(s, 0, 0);*returnSize = resultTop;  // 设置返回的IP地址数量return result;
}

复杂度分析

  • 时间复杂度:O(n!),回溯尝试所有可能分割方式。
  • 空间复杂度:O(n!),存储所有可能的IP地址。

关键点说明

  1. 回溯终止条件:当分割点数为3时,验证最后一段。
  2. 剪枝优化:遇到无效分割时立即终止当前循环。
  3. 动态内存管理:结果字符串需动态分配,并适时扩展结果数组。

总结

通过回溯法遍历所有可能的分割方式,结合有效性剪枝,可高效生成所有合法IP地址。注意处理边界条件(如前导零、数值范围)和内存管理,确保程序健壮性。

相关文章:

每日一题——将数字字符串转化为IP地址

将数字字符串转化为IP地址 题目描述解题思路回溯法步骤分解 代码实现全局变量有效性验证函数回溯函数主函数完整代码 复杂度分析关键点说明总结 这题难度还挺大的&#xff0c;整体上实现并不容易。建议参考视频 和https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%…...

机器学习数学基础:25.随机变量分布详解

一、随机变量与分布函数的基本概念 &#xff08;一&#xff09;什么是随机变量&#xff1f; 在概率论领域&#xff0c;随机变量是将随机试验的结果进行数值化的关键概念。它就像一座桥梁&#xff0c;把抽象的随机事件和具体的数学分析连接起来。 举例来说&#xff0c;在一个…...

香港电讯与Zenlayer达成战略合作,拓展全球互联生态圈

作为主要国际金融与贸易中心&#xff0c;香港一直是连系中国内地及全球市场的重要门户。香港电讯作为本地领先的综合电讯服务提供商&#xff0c;拥有广泛的网络资源和深厚的技术专长&#xff0c;一直支持国内企业“走出去”和外资企业“走进来”。而旗下由PCCW Global营运的Con…...

MySQL-事务隔离级别

事务有四大特性&#xff08;ACID&#xff09;&#xff1a;原子性&#xff0c;一致性&#xff0c;隔离性和持久性。隔离性一般在事务并发的时候需要保证事务的隔离性&#xff0c;事务并发会出现很多问题&#xff0c;包括脏写&#xff0c;脏读&#xff0c;不可重复读&#xff0c;…...

【Python学习 / 6】面向对象编程(OOP)

文章目录 ⭐前言⭐一、类和对象&#xff1a;面向对象编程基础1. 类&#xff08;Class&#xff09;类的组成&#xff1a;例子&#xff1a;定义一个简单的 Dog 类代码解析&#xff1a; 2. 对象&#xff08;Object&#xff09;对象的创建&#xff1a; 3. 三大特性&#xff1a;封装…...

Ollama DeepSeek + AnythingLLM 实现本地私有AI知识库

Ollama DeepSeek AnythingLLM 实现本地私有AI知识库 本地部署DeepSeek-r1下载安装AnythingLLMAnythingLLM 配置LLM首选项Embedder首选项向量数据库工作区其他配置 AnythingLLM Workspace使用上传知识词嵌入知识检索 本文主要介绍了如何使用AnythingLLM结合Ollama部署的DeepSee…...

个人博客测试报告

一、项目背景 个人博客系统采用前后端分离的方法来实现&#xff0c;同时使用了数据库来存储相关的数据&#xff0c;同时将其部署到云服务器上。前端主要有四个页面构成&#xff1a;登录页、列表页、详情页以及编辑页&#xff0c;以上模拟实现了最简单的个人博客系统。其结合后…...

嵌入式八股文(四)计算机网络篇

第一章 基础概念 1. 服务 指网络中各层为紧邻的上层提供的功能调用,是垂直的。包括面向连接服务、无连接服务、可靠服务、不可靠服务。 2. 协议 是计算机⽹络相互通信的对等层实体之间交换信息时必须遵守的规则或约定的集合。⽹络协议的三个基本要素:语法、…...

基于Electron+Vue3创建桌面应用

Electron 是一个开源框架,基于 Chromium 和 Node.js,用于开发跨平台桌面应用程序。它允许开发者使用 HTML、CSS 和 JavaScript 等 Web 技术构建原生桌面应用,支持 Windows、macOS 和 Linux。Electron 以其开发便捷性、强大的功能和丰富的生态系统而广泛应用于工具类应用、媒…...

建立稳定分析模式的模式语言01

Haitham Hamza 等 著&#xff0c;wnb 译 摘要 一般认为&#xff0c;软件分析模式在减少开销和缩短软件产品生命周期等方面会起到重要的作用。然而&#xff0c;分析模式的巨大潜能还未被充分发掘。缺乏稳定性是当前分析模式存在的主要问题。多数情况下&#xff0c;为特定问题建…...

【C++游戏开发-五子棋】

使用C开发五子棋游戏的详细实现方案&#xff0c;涵盖核心逻辑、界面设计和AI对战功能&#xff1a; 1. 项目结构 FiveChess/ ├── include/ │ ├── Board.h // 棋盘类 │ ├── Player.h // 玩家类 │ ├── AI.h // AI类 │ └── Game.h // 游戏主逻辑 ├── src/ …...

ubuntu20动态修改ip,springboot中yaml的内容的读取,修改,写入

文章目录 前言引入包yaml原始内容操作目标具体代码执行查看结果总结: 前言 之前有个需求&#xff0c;动态修改ubuntu20的ip&#xff0c;看了下&#xff1a; 本质上是修改01-netcfg.yaml文件&#xff0c;然后执行netplan apply就可以了。 所以&#xff0c;需求就变成了 如何对ya…...

tailwindcss学习02

vue中接入tailwindcss 使用cmd不要使用powershell npm create vitelatest stu02 -- --template vue cd stu02npm install --registry http://registry.npm.taobao.org npm install -D tailwindcss3.4.17 postcss autoprefixer --registry http://registry.npm.taobao.org npx t…...

千峰React:脚手架准备+JSX基础

组件化->封装性 React提供函数组件实现组件化 React和传统JS的区别就是JS需要手动管理DOM操作&#xff0c;React: 采用组件化开发&#xff0c;通过虚拟DOM提升性能。 MVC 是一种软件设计模式&#xff0c;全称为 Model-View-Controller&#xff08;模型-视图-控制器&#x…...

【算法】快排

题目 快排 思路 如果输入为0或1直接返回&#xff1b;否则取一个基准值&#xff0c;可以取中间位置&#xff0c;如果输入是有序的可以避免时间过长&#xff0c;然后移动指针&#xff0c;先让i指针右移&#xff0c;如果小于基准值就继续右移&#xff0c;j指针左移同理。如果指…...

开放签电子签章工具版 2.0 正式发布,构建全场景电子签约能力、满足复杂的签章管理场景

根据近半年开源用户和市场需求反馈&#xff0c;开放签团队推出电子签章工具版2.0版本&#xff0c;主要解决复杂的签约流程集成和电子印章授权管理场景。以API接口对外提供服务和配置一套可视化后台管理系统&#xff0c;可与业务系统无缝集成&#xff0c;用户使用起来毫无“违和…...

python和pycharm 和Anaconda的关系

好的&#xff0c;下面我会详细说明 Python、PyCharm 和 Anaconda 三者的关系&#xff0c;并逐一解释它们的功能和作用。 1. Python&#xff08;编程语言&#xff09; 定义&#xff1a;Python 是一种高级编程语言&#xff0c;设计简洁&#xff0c;易于学习&#xff0c;且功能强…...

DeepSeek V3和R1

DeepSeek V3 和 R1 是深度求索&#xff08;DeepSeek&#xff09;推出的两款大模型&#xff0c;基于混合专家架构&#xff08;MoE&#xff09;&#xff0c;但在设计目标、训练方法和应用场景上存在显著差异。以下是两者的详细对比与补充内容&#xff1a; DeepSeek V3和R1 一、模…...

JavaScript数组-获取数组中的元素

在JavaScript中&#xff0c;数组是一种非常实用的数据结构&#xff0c;它允许我们将多个值存储在一个单独的变量中。无论是数字、字符串还是对象&#xff0c;都可以作为数组的元素。获取数组中的特定元素是操作数组的基础技能之一。本文将详细介绍如何在JavaScript中获取数组中…...

SSE:用于流式传输的协议

一.什么是SSE SSE协议是一种基于http协议的单向通信协议&#xff0c;服务端可以向客户端发送数据&#xff0c;但是客户端不能向服务器发送数据。客户端通过创建一个到服务器的单向连接来监听事件。可以将一次性返回数据包改为流式返回数据。SSE协议支持断线重连&#xff0c;也支…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...