You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于递归函数生成指定字符串的合法IP地址:代码调试求助

问题分析与修复方案

你的代码主要存在参数设计混乱、合法性判断缺失、递归逻辑错误这几个核心问题,导致无法正确生成合法IP地址。我们先拆解原代码的错误点,再给出正确的实现:

原代码的关键错误

  1. 冗余且错误的参数传递endIndexstrNum完全没必要作为递归参数,而且递归时的字符串截取逻辑s.substring(i,startIndex + endIndex)完全错误,会导致截取的片段混乱。
  2. IP段合法性判断缺失:没有处理前导零的情况(比如"01"是非法IP段,只有单个"0"是合法的),且判断数值范围的时机错误,导致非法片段被加入组合。
  3. 递归终止与循环逻辑混乱
    • 终止条件判断顺序错误,应该先检查是否已经选满4段,再验证是否用完了整个字符串。
    • 循环遍历范围错误,IP段最多只能是3位,不需要遍历到字符串末尾,只需要从当前索引尝试截取1-3位即可。
  4. 回溯逻辑错误combination.addremove的时机不对,导致回溯时无法正确撤销选择。

正确的递归实现代码

以下是修复后的Java代码,完全符合你的需求:

import java.util.ArrayList;
import java.util.List;

public class IpRestorer {
    public static void main(String[] args) {
        String s = "25525511135";
        List<List<String>> results = new ArrayList<>();
        restoreIp(s, results, new ArrayList<>(), 0, 0);
        // 打印结果,和预期一致
        System.out.println(results);
    }

    private static void restoreIp(String s, List<List<String>> results, List<String> current, int start, int segments) {
        // 终止条件:选了4段,且刚好用完整个字符串
        if (segments == 4) {
            if (start == s.length()) {
                results.add(new ArrayList<>(current));
            }
            return;
        }

        // 尝试截取1-3位作为当前IP段(最多3位,且不能超过字符串长度)
        for (int i = start; i < start + 3 && i < s.length(); i++) {
            String segment = s.substring(start, i + 1);
            // 检查IP段合法性:
            // 1. 数值在0-255之间
            // 2. 没有前导零(除非是单个"0")
            if (isValidSegment(segment)) {
                current.add(segment);
                // 递归:下一段从i+1开始,段数+1
                restoreIp(s, results, current, i + 1, segments + 1);
                // 回溯:撤销当前选择
                current.remove(current.size() - 1);
            }
        }
    }

    private static boolean isValidSegment(String segment) {
        // 长度超过3直接非法
        if (segment.length() > 3) {
            return false;
        }
        // 前导零的情况:长度>1且以0开头,非法
        if (segment.length() > 1 && segment.startsWith("0")) {
            return false;
        }
        // 转换为数字检查范围
        int num = Integer.parseInt(segment);
        return num >= 0 && num <= 255;
    }
}

代码逻辑说明

  1. 递归参数
    • start:当前截取IP段的起始索引
    • segments:已经选好的IP段数量(最多4段)
  2. 终止条件:当选满4段时,只有当start等于字符串长度(说明刚好把所有字符用完),才将当前组合加入结果。
  3. 循环逻辑:每次从start开始,尝试截取1-3位字符(因为IP段最多3位),避免无效遍历。
  4. 合法性校验:单独提取isValidSegment方法,清晰判断IP段是否合法,重点处理前导零的情况。
  5. 回溯操作:加入当前合法段后递归,递归返回后移除该段,恢复状态以尝试下一种可能。

运行这段代码后,你会得到预期的结果:[["255","255","11","135"], ["255","255","111","35"]]

内容的提问来源于stack exchange,提问作者Abdusoli

火山引擎 最新活动