java数据结构与算法刷题-----LeetCode93. 复原 IP 地址

本文介绍了使用Java编程解决IP地址分割问题的方法,通过回溯算法遍历所有可能的分割组合,确保每段IP符合规则,同时分析了时间复杂度为O(3^IP段数*s)和空间复杂度为O(IP段数)的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.youkuaiyun.com/grd_java/article/details/123063846

文章目录

在这里插入图片描述

解题思路:时间复杂度O( 3 I P 段数 ∗ s 3^{IP段数} * s 3IP段数s),ip段数为4,s是字符串长度,空间复杂度O(IP段数)
  1. 题目并不是只要一种分割方案,所以需要回溯算法枚举
  2. IP地址需要分4段,第四段末尾不需要加点。并且第四段数字必须截止到字符串末尾(题目要求的)
  3. 前3段需要末尾加点,而分割数字的个数随便。
  4. 每次分割完,需要判断分割后的数字是否合法

例如25525511135这个例子,第一次分割2.第二次分割5,是满足条件的。但是如果第二次分割552的话,就不满足了,因为每个字段最大只能是255.

代码

在这里插入图片描述

// 回溯 状态是一个字符串
class Solution {
    char sToArr[];
    int len;
    // 回溯 状态是一个字符串
    List<String> res = new ArrayList<>();

    /**
     * 判断当前子串是否合法
     * @param start 子串起始位置
     * @param end 子串结束位置
     * @return 是否满足ip地址规则
     */
    public boolean isValid(int start, int end) {
        if (end - start + 1 >= 4 || end < start) return false;//不可以超过3个数字
        if (sToArr[start] == '0' && end != start) return false;//除了单个0以外,其它情况不能以0开头,比如192.01.0.1是非法ip
        int sum = 0;//计算当前字段的值
        for (int i = start; i <= end; i++) {
            sum = sum * 10 + sToArr[i] - '0';
        }
        if (sum > 255) return false;//如果超出255,就不合法
        return true;
    }
    //程序入口
    public List<String> restoreIpAddresses(String s) {
        sToArr = s.toCharArray();//为了少传参,增加代码可读性,将字符串s保存到全局变量中
        len = s.length();
        char[] ip = new char[len+3];//保存当前ip地址
        backTracking( 1, 0, ip, 0);//回溯枚举
        return res;//返回答案
    }

    // start表示从哪个元素后面开始分割 index表示放的是第几个

    /**
     * 回溯
     * @param pointNum 当前是第几个字段,如果是最后一个,子串长度就是start到字符串末尾
     * @param start 子串起始位置
     * @param ip 保存当前ip地址
     * @param ipIndex ip数组的下标
     */
    public void backTracking( int pointNum, int start, char[] ip, int ipIndex) {
        if (pointNum == 4) {//如果pointNum是最后一个字段,那么子串要从start截止到末尾
            if (!isValid(start, len - 1)) return;//如果当前字段的数字满足ip条件
            for (int i = start; i < len; i++) ip[ipIndex++] = sToArr[i];//将其添加到答案中
            res.add(new String(ip, 0, ipIndex));
            return;
        }
        //如果不是最后一个字段,就正常枚举
        int temp = ipIndex;//保存当前字段的起始下标
        for (int i = start; i <= start + 2 && i < len; i++) {//每次每个字段最多枚举3个字符,因为4个字符一定不满足ip地址规则
            if (!isValid( start, i)) continue;//如果当前截取的子串不符合规则,就跳过这次,进行下次枚举
            for (int j = start; j <= i; j++) ip[temp++] = sToArr[j];//满足条件后,记录到ip中
            ip[temp++] = '.';//前3个字段,末尾需要加"."
            backTracking( pointNum + 1, i + 1, ip, temp);//进行下一个字段的枚举
            temp = ipIndex;//上面回溯枚举完成后,这里需要重新枚举此字段,temp重新执行当前字段起始下标
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ydenergy_殷志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值