每日一题--复原 IP 地址

134 阅读2分钟

这是我参与11月更文挑战的第9天,活动详情查看:[2021最后一次更文挑战]

题目

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 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 地址。

示例 1:

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

思路

以 "25525511135" 为例,第一步时我们有几种选择? 选 "2" 作为第一个片段 选 "25" 作为第一个片段 选 "255" 作为第一个片段 能切三种不同的长度,切第二个片段时,又面临三种选择。 这会向下分支形成一棵树,我们用 DFS 去遍历所有选择,必要时提前回溯。 因为某一步的选择可能是错的,得不到正确的结果,不要往下做了。撤销最后一个选择,回到选择前的状态,去试另一个选择。

回溯的第一个要点:选择,它展开了一颗空间树。

回溯的要点二——约束 约束条件限制了当前的选项,这道题的约束条件是: 一个片段的长度是 13 片段的值范围是 0255 不能是 "0x"、"0xx" 形式(测试用例告诉我们的) 用这些约束进行充分地剪枝,去掉一些选择,避免搜索「不会产生正确答案」的分支。

回溯的要点三——目标 目标决定了什么时候捕获答案,什么时候砍掉死支,回溯。 目标是生成 4 个有效片段,并且要耗尽 IP 的字符。 当满足该条件时,说明生成了一个有效组合,加入解集,结束当前递归,继续探索别的分支。 如果满4个有效片段,但没耗尽字符,不是想要的解,不继续往下递归,提前回溯。

代码

    const res = [], path = [];
    backtracking(0, 0);
    return res;
    function backtracking(i) {
        const len = path.length;
        if(len > 4) return;
        if(len === 4 && i === s.length) {
            res.push(path.join('.'));
            return
        } 
        for(let j = i; j < s.length; j++) {
            const str = s.substr(i, j - i + 1);
            if(str.length > 3 || +str > 255) break;
            if(str.length > 1 && str[0] === "0") break;
            path.push(str);
            backtracking(j + 1);
            path.pop()
        }
    }
};