刷题打卡:字符串操作の 复原 IP 地址

129 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目描述:

复原 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 中的任何数字。你可以按 任何 顺序返回答案。

示例 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"]

二、思路与实现:

思路:

长度>12的字符串,一定无法分割,返回空数组;

从i开始遍历,去除0开头的情况和大于255的情况,然后在j+1位插入‘.’,递归查找下标为j+2,层级k+1的情况

如果查找到第四级不符合条件,需要回溯的过程中把j+1位置的‘.’去除

代码实现:

/**
 * @param {string} s
 * @return {string[]}
 */
var restoreIpAddresses = function(s) {
    if (s.length > 12) return []; 
    let res = new Set(); // 用set去重
    function toNum(str) {
        return +str;
    }
    function check(n) {
        if (n.length > 1 && n[0] === '0') return false; // 含有前导零的,长度不为1的字符串,非法,返回false。
        return toNum(n) >= 0 && toNum(n) <= 255; 
    }
    function bct(path = [], remain = 3, start = 1) { // 回溯:path记录三个点符号的位置。remain记录剩余点的数目。
        if (remain === 0) {
            let a = s.slice(0, path[0]);
            let b = s.slice(path[0], path[1]);
            let c = s.slice(path[1], path[2]);
            let d = s.slice(path[2]);
            if (check(a) && check(b) && check(c) && check(d)) {
                res.add(`${a}.${b}.${c}.${d}`);
            }
            return;
        }
        let e = Math.min(start+3, s.length); // 最多只能向后走三位,且不能超出字符串的长度。
        for (let i=start; i<e; i++) {
            path.push(i);
            bct(path, remain-1, i+1);
            path.pop();
        }
    }
    bct();
    return Array.from(res);
};

三、总结:

本题考察回溯,回溯仍是必须要掌握的算法。

虽然回溯算法由于“指数爆炸”通常不适用于大规模的计算,但它仍然是算法领域里一个重要组成,甚至很多时候是最优解。

在特定的问题下,稍加改动就能通向很多其他算法分支——动态规划、记忆化搜索等。