算法学习记录(九十七)

93 阅读1分钟

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

image.png

解:

  1. 目标就是把字符串分成四份,并且不含有前导零并且小于等于255
  2. 递归函数的参数含义为,idx:当前在第几个字符,num:当前是第几份,preStr:idx之前的字符切分情况
  3. 从第0个字符,第0份开始递归
  4. 对每一份来说,可以选1 ~ 3个字符,遍历1 ~ 3,截取从idx开始往后的字符,排除前导0和大于255的情况,把截取的字符拼接到preStr后,往下一份去递归,递归结束后将preStr重置为拼接前的值
  5. 当来到第4份时,同时也没有剩余字符,说明这是一组正确的解,放入结果数组中
const restoreIpAddresses = function(s) {
    const res = []
    // idx: 当前在第几个字符   num:当前是第几个.
    function getRes(idx, num, preStr) {
        // num越界并且idx刚好走完,表明这是一种成功的结果
        if (num === 4) {
            if (idx === s.length) {
                res.push(preStr)
            }
            return
        }
        // 记录preStr,递归完回溯
        const tempStr = preStr
        for (let i = 1; i < 4; i++) {
            const str = s.substr(idx, i)
            // 排除前导0和大于255的情况
            if (!(str.length > 1 && str[0] === '0') && +str <= 255) {
                preStr += num === 3 ? str : str + '.'
                getRes(idx + i, num + 1, preStr)
                preStr = tempStr
            }
        }
    }
    getRes(0, 0, '')
    return res
};