93. 复原 IP 地址

144 阅读2分钟

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

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

解法:
方法一 暴力解法

func restoreIpAddresses(s string) []string {
    if len(s) == 0 {
        return nil
    }
   
    length := len(s)
    ans := make([]string, 0)
    iStart := 0
    for i := 0; i < 3 && i < length; i ++ {
        if !validate(s[iStart:i + 1]) {
            continue
        } 
        str := s[iStart:i + 1]
        jStart := i + 1
        for j := i + 1; j <= i + 3 && j < length; j ++ {
            
            if !validate(s[jStart:j + 1]) {
                continue
            } 
            // 这里要重新初始化变量,否则会和上次循环的secStr拼接在一起
            secStr := str + "." + s[jStart:j + 1]   
            kStart := j + 1         
            for k := j + 1; k <= j + 3 && k < length; k ++ {
                if !validate(s[kStart:k + 1]) || !validate(s[k + 1:length]) {
                    continue
                } 
                // 这里要重新初始化变量,否则会和上次循环的finalStr拼接在一起
                finalStr := secStr + "." + s[kStart:k + 1]  + "." + s[k + 1:length]
                ans = append(ans, finalStr)
            }
        }
    }
    return ans
}

// 判断字符串是否在范围[0:255]
func validate(str string) bool {
    if len(str) == 0 {
        return false
    }
    if str== "0" {
        return true
    }
    if str[0] == '0' {
        return false
    }
    n, _ := strconv.Atoi(str)
    return 0 <= n && n <= 255
}

方法二 回溯

import "strings"
var segments []string
var maxSegId = 3
var ans []string

func restoreIpAddresses(s string) []string {
    if len(s) == 0 {
        return nil
    }
   

    segments = make([]string, 4)
    ans = make([]string, 0)
    dfs(s, 0, 0)
    return ans
}


func dfs(s string, segId, segStart int) {
    // 填充完毕,返回
    if segId == 4 {
        return
    }
    // 遍历到IP的最后8位了
    if segId == maxSegId {
        if validate(s[segStart:len(s)]) {
            // 回溯的精髓在这里,设置segments[segId]
            segments[segId] = s[segStart:len(s)]
            ans = append(ans, strings.Join(segments, "."))
        }
    }

    // 当前位等于‘0’
    if s[segStart:len(s)] == "0" {
         segments[segId] = "0"
         dfs(s, segId + 1, segStart + 1)
    }
    // 遍历
    for end := segStart ; end <= segStart + 2 && end < len(s); end ++ {
        curStr := s[segStart: end + 1]
        if !validate(curStr) {
            continue
        }
        segments[segId] = curStr
        dfs(s, segId + 1, end + 1)
    }
}

// [0:255]
func validate(str string) bool {
    if len(str) == 0 {
        return false
    }
    if str== "0" {
        return true
    }
    if str[0] == '0' {
        return false
    }
    n, _ := strconv.Atoi(str)
    return 0 <= n && n <= 255
}