回溯算法06-复原IP地址(Java/分割字符串)

6.复原IP地址

  • 题目描述

有效 IP 地址 正好由四个整数(每个整数位于 0255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

  • 例如:"0.1.2.201" "192.168.1.1"有效 IP 地址,但是 "0.011.255.245""192.168.1.312""192.168@1.1"无效 IP 地址。

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

示例 1:

输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]

示例 2:

输入:s = "0000"
输出:["0.0.0.0"]

示例 3:

输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
  • 思路分析
本题本质上是一个切割字符串的问题,并且要求切割的子串满足一定的规律,我们仍然可以用回溯算法去解决此类问题。这一我们上一题目分割回文子串方法很相近,只是多了一步在小数点的增添,下面我们以一个例子来分析一下本题的解法

image-20240307121445277

1.初始化:
使用StringBuilder来构建当前的IPv4地址段(称为path)。
使用ArrayList来保存所有找到的有效IPv4地址(称为result)。

2.回溯函数 backtrack(String s, int pointSum):
s是当前还未处理的字符串部分。
pointSum表示当前已经添加了多少个点(即,已经找到了多少个数字段)。
每次通过检验未处理的字符串部分来进行递归

3.终止条件:
当pointSum等于3时,意味着我们已经找到了三个点,即四个数字段。此时,我们需要检查剩余的字符串s是否有效,并且长度不为0(因为每个数字段至少包含一个字符)。如果满足条件,则将当前path中的字符串添加到result中,并回退状态。

4.回溯搜索:
在每次回溯调用中,我们遍历字符串s的所有可能的前缀,检查它们是否是有效的数字段(通过isValid函数)。
如果找到有效的数字段,我们将其添加到path中,并添加一个点。
然后,我们对剩余的字符串s的剩余部分进行递归回溯调用。
在递归返回后,我们需要回退状态,即从path中删除之前添加的数字段和点,并将pointSum减1,以便尝试其他可能的组合。
  • Java代码实现
StringBuilder path = new StringBuilder();
    List<String> result = new ArrayList<>();
    public List<String> restoreIpAddresses(String s) {
        backtrack(s, 0);
        return result;
    }

    private void backtrack(String s, int pointSum) {
        if (pointSum == 3) {
            if (!s.equals("") && isValid(s)) {
                path.append(s);
                result.add(new String(path));
                path.delete(path.length() - s.length(), path.length());
            }
            return;
        }

        for (int i = 0; i < s.length(); i++) {
            String before = s.substring(0, i + 1);
            if (isValid(before)) {
                path.append(before);
                path.append(".");
                pointSum++;
                String after = s.substring(i + 1);
                backtrack(after, pointSum);
                path.delete(path.length() - before.length() - 1, path.length());
                pointSum--;
            }
        }
    }

    private Boolean isValid(String s) {
        if (s.length() != 1 && s.charAt(0) == '0') { // 0开头的数字不合法
            return false;
        }
        int num = 0;
        for (int i = 0; i < s.length(); i++) {
            num = num * 10 + (s.charAt(i) - '0');
            if (num > 255) { // 如果⼤于255了不合法
                return false;
            }
        }
        return true;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值