当前位置: 首页 > 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;也支…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...