回溯:复原IP地址

94 阅读1分钟

leetcode: 93. 复原 IP 地址

题目描述

有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 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 中的任何数字。你可以按 任何 顺序返回答案。

示例

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

解题思路

image.png

比较简单的回溯,重点是剪枝细节比较多。

  • 字符串长度小于4或者大于12 不可能得到合法的ip地址。
  • 当前part小于最小长度限制(不回溯,continue)
  • 非0值存在前导0剪枝
  • 多个0组成的0值剪枝
  • 当前part超过最大值剪枝

完整代码:

class Solution {
    List<String> res;
    StringBuilder path;

    public List<String> restoreIpAddresses(String s) {
        int n = s.length();
        if (n < 4 || n > 12) return new ArrayList<>();

        res = new ArrayList<>();
        path = new StringBuilder();
        backtrack(s, 0, 0);
        return res;
    }

    void backtrack(String s, int start, int parts) {
        if (parts >= 4) {
            res.add(path.toString());
        }

        int n = s.length();
        char[] cs = s.toCharArray();
        for (int i = start; i < n; i++) {
            if (parts == 3) i = n - 1;

            int subLen = i - start + 1;
            String sub = s.substring(start, i + 1);
            if (subLen < n - path.length() + parts - 3 * (3 - parts)) continue;

            int num = Integer.parseInt(sub);
            if (0 != num && sub.charAt(0) == '0') return;
            if (0 == num && subLen > 1) return;
            if (num > 255) return;

            int pre = path.length();
            path.append(sub);
            if (parts < 3) path.append('.');
            backtrack(s, i + 1, parts + 1);
            path.delete(pre, path.length());
        }
    }
}