题解 | #数字字符串转化成IP地址#

数字字符串转化成IP地址

https://www.nowcoder.com/practice/ce73540d47374dbe85b3125f57727e1e

想象一下递归树的结构,其中每个节点代表当前递归的状态。在这个特定的问题中,我们要解决的问题是将字符串 s 划分为四个IPv4地址段。

以下是如何可视化 restoreIpAddresses 方法的递归过程:

  1. 根节点:代表初始状态,tmp 和 res 为空,cur 为 0,表示我们从字符串 s 的开始处进行划分。
  2. 分支:每个节点根据当前索引 cur 可以生成1到3位的数字段(不能以0开头,除非数字段是0本身)。每个可能的数字段都是一个分支。
  3. 深度优先搜索(DFS):从根节点开始,我们沿着每个分支向下搜索,直到无法继续生成有效的数字段或达到字符串的末尾。
  4. 剪枝:在搜索过程中,我们使用剪枝条件来减少不必要的搜索:如果当前未处理的字符串长度 s.length() - cur 大于剩余段数乘以3,提前返回(因为不可能生成足够的段)。如果小于剩余段数,也提前返回(因为当前剩余的字符串长度不足以生成所需的段数)。
  5. 回溯:在每个分支的末尾,我们使用 tmp.remove(tmp.size() - 1) 进行回溯。这表示我们撤销了上一步的决策,回到前一个状态,然后尝试下一个可能的数字段。
  6. 构建结果:当我们成功地生成了四个段,并且所有的字符都被使用时(tmp.size() == 4 && cur == s.length()),我们将这些段组合成一个IPv4地址,并将其添加到结果列表 res 中。
  7. 终止条件:如果 tmp 中的段数已经达到4,并且当前索引 cur 等于字符串 s 的长度,我们找到了一个有效的IPv4地址组合。
  8. 前导0的处理:如果生成的数字段 num 为0,并且当前索引 i 不等于起始索引 cur(即存在前导0),则使用 break 退出当前循环,避免将无效的段加入到 tmp 中。

可视化这个过程,可以想象一个树状图,其中每个节点代表一个递归调用的状态,每个节点的子节点代表从该状态生成的所有可能的数字段。树的深度为字符串 s 的长度,宽度为可能的数字段的组合数量。

通过这种方式,我们可以清晰地看到递归过程中的所有可能路径,以及如何通过回溯来探索不同的组合。这也展示了为什么不需要清空 tmp:因为我们希望保留之前的决策,以便在回溯时可以重新使用它们。

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param s string字符串 
     * @return string字符串ArrayList
     */
     ArrayList<String> res=new ArrayList<>();
    ArrayList<String> tmp=new ArrayList<>();
     
    public ArrayList<String> restoreIpAddresses (String s) {
        // write code here
        // 限制每一个[1,3]位置以及如果是3,那么数字小于255,否则,挪给别的,
        // >1则不能以0开头
        // 根据位数判断
        dfs(s,0);
        return res;

      }
      public void dfs(String s,int cur)
      {
        if(tmp.size()==4&& cur==s.length())
        {
            res.add(tmp.get(0)+"."+tmp.get(1)+"."+tmp.get(2)+"."+tmp.get(3));
        }
        if(s.length()-cur>3*(4-tmp.size()))//每段大于3
        {
            return;
        }
        if(s.length()-cur<4-tmp.size())//小于1
        {
            return;
        }
        int num=0;
        for(int i=cur;i<cur+3&&i<s.length();i++)//一个一个数字的判断
        {//0,1,2
            num=num*10+(s.charAt(i)-'0');//数字
            if(num<0||num>255)//数字越界了就不要了,

            {
                break;
            }
            tmp.add(s.substring(cur,i+1));//截取【0,255】之间的数字
            dfs(s,i+1);//继续判断
            tmp.remove(tmp.size()-1);//为啥?
            // 回溯允许算法“回到”上一个状态,重新考虑不同的数字组合。
            if(num==0)
            {
                break;//只能0.不能02|09这些
            }


        }
      }
}

全部评论

相关推荐

10-23 16:33
门头沟学院 Java
本人某中9本科,成绩中等,目前没科研没实习,目前后端学到了javaWeb,开始没定好方向,在学国外课程,走工程路线起步有点晚了,到这个时间点了还在学JavaWeb,顿感迷茫,不知道是坚持走下去还是寒假去准备考研。考研这个路弄得我还是心痒痒的,因为从众考研的人也不在少数,所以会有这方面的心理安慰吧,就是“不行我可以去考研啊”,而且意味着三年的缓冲,为了复试还有积攒经验美化简历,其实现在也可以去申入实验室打杂;就业可能意味着多些工作经验,工程岗应该到后面还是经验大于学历?还是有点迷茫了,求助好心人有无路线启发
千千倩倩:同27给点建议,现在这个时间点可以快速看完外卖和点评,不用跟着敲,但一定要在看的时候总结每个部分的整个业务流程,对其中的实现有一个大概的印象。然后直接开始看八股,刷算法。八股和算法最好还是在项目学习中穿插着看。如果计算机基础,算法这些基础好,加上每天刻苦学习,两周可以达到勉强能面试的水平,到时候就直接海投中小厂,在约面和面试的过程中不断巩固知识。没找到实习也没关系,就当积累经验。再沉淀一波直接明年三月开始投暑期,毕竟是9本,总是有面试机会的,只要你这三个月不懈怠,面试发挥得一定不错,只要拿到一个中,大厂暑期实习,秋招就有竞争力了。总得而言,现在还有机会,但是时间非常紧张,需要你结合自己情况考虑,共勉
你会选择考研还是直接就业
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务