复原 IP 地址

167 阅读1分钟

题目描述

有效 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"]

分析题意

无效的IP地址:

  • IP地址超过四段
  • IP地址的每段长度超过3位数
  • IP地址每段的第一个数为0,后面两位或一位不为0,例如:01,011等
  • IP地址每段>255

思路

  1. 对于切割问题,首先想到:回溯算法,先抽象为树形结构

image.png

  1. 回溯算法

    • 终止条件: path.length==4&&startIndex==s.length (表示:IP地址为4段并且此时s字符串已经全部遍历完成)
    • 传参:s(字符串),startIndex:(表示每次从何处开始切割)
    • 单层递归逻辑:
     for(let i=startIndex;i<s.length;i++){
             //判断是否合法
            if(isVaild(s,startIndex,i)){
                //添加合法路径
                path.push(s.slice(startIndex,i+1));
                // 递归下一次切割
                backTracking(s,i+1);
                // 回溯操作
                path.pop();
            }else{
                continue
            }
        }
    

完整代码

function restoreIpAddresses(s: string): string[] {
    let result=[],path=[];
    //递归方法
    function backTracking(s:string,startIndex:number):void{
        //终止条件
        if(path.length==4&&startIndex==s.length){
            result.push(path.join("."));
            return;
        }
        //单层递归
        for(let i=startIndex;i<s.length;i++){
            if(isVaild(s,startIndex,i)){
                path.push(s.slice(startIndex,i+1));
                backTracking(s,i+1);
                path.pop();
            }else{
                continue
            }
        }

    }

    //判断数字是否合法
    function isVaild(s:string,start:number,end:number):boolean{
        let news=s.slice(start,end+1);
        if(news.length > 3 || +news > 255) return false;
        if(news.length > 1 && news[0] === "0") return false;

            return true
    }

    backTracking(s,0);
    return result;
};

image.png

总结

本题与切割回文串思路类似,遇到组合,切割等问题时,优先考虑回溯算法,将其抽象为一个树形结构,可以使我们更好的理解。