递归与回溯:93.复原IP地址

2020-12-09  本文已影响0人  zmfflying

/**

题目

给定一个只包含数字的字符串,复原它并返回所有可能的 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"]
示例 2:

输入:s = "0000"
输出:["0.0.0.0"]
示例 3:

输入:s = "1111"
输出:["1.1.1.1"]
示例 4:

输入:s = "010010"
输出:["0.10.0.10","0.100.1.0"]
示例 5:

输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]

提示:
0 <= s.length <= 3000
s 仅由数字组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/restore-ip-addresses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

测试代码

print(restoreIpAddresses("25525511135"))

笔记

具体的逻辑见代码和注释,这里写一下核心笔记
这道题和普通递归的差别在于比较复杂的边界判断 和 递归里有循环
但其实核心还是一样的,都是要每次获取到合适的 数据

这次递归是从前到后,每次取到 0~255 之间的字符串
所以每次递归里有循环 和 边界判断

最终判断条件是 已经取到了4个有效数据后,如果字符串已经走完就是有效数据,如果字符串还没走完就是无效数据

代码地址

https://github.com/zmfflying/ZMathCode
*/

解题代码

import Foundation

func restoreIpAddresses(_ s: String) -> [String] {
    let total = 4
    //res 是最终结果数组 存完整的ip 如 ["255.255.11.135","255.255.111.35"]
    var res: [String] = [String]()
    //cur 是当前的字符串数组 如 ["255","255","111","35"]
    //注意 cur在同一时刻是唯一的
    var cur: [String] = [String]()
    
    //strArr 不做改变 startIndex 是本次递归的开始节点
    func help(strArr: [Character], startIndex: Int) {
        //如果 cur 已经是有4个,但是字符串还没走完,说明本次数据 cur 错误,直接返回
        if strArr.count > startIndex && cur.count == total {
            return
        }
        //如果 cur 已经是有4个,字符串也已经走完,说明本次数据 cur 正确,加入 res 中
        if strArr.count == startIndex && cur.count == total {
            let ss = cur.joined(separator: ".")
            res.append(ss)
            return
        }

        //因为是 0 ~ 255 所以最多也就3位
        for length in 1...3 {
            //计算出当前节点
            let curIndex = startIndex + length
            //这里有两种数据无效情况
            //1.当前节点已经超出字符串数组大小
            //2.本次字符串是 01 这样的数据
            if curIndex - 1 >= strArr.count || (length != 1 && strArr[startIndex] == "0") {
                return
            }
            //取出本次的字符串 如 25
            let newStr = String(strArr[startIndex ..< curIndex])
            //这里是边界判断 大于255的数据不要
            if length == 3 && Int(newStr)! > 255 {
                return
            }
            //cur 里增加本次有效的字符串并开始下次遍历
            cur.append(newStr)
            help(strArr: strArr, startIndex: curIndex)
            //到这里 cur 的数据已经被改变,最后的元素是上次增加的数据,
            //需要丢弃才能保证下次循环的数据正确
            cur.removeLast()
        }
    }

    help(strArr: Array(s), startIndex: 0)
    return res
}

上一篇下一篇

猜你喜欢

热点阅读