算法leetcode|93. 复原 IP 地址(多语言实现)


文章目录


93. 复原 IP 地址:

有效 IP 地址 正好由四个整数(每个整数位于 0255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

  • 例如:"0.1.2.201""192.168.1.1"有效 IP 地址,但是 "0.011.255.245""192.168.1.312""[email protected]"无效 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"]

提示:

  • 1 <= s.length <= 20
  • s 仅由数字组成

分析:

  • 面对这道算法题目,二当家的再次陷入了沉思。
  • ip地址大家都是知道的,ipv4是由4段组成,每段的取值范围都是 [0,255]。
  • 给出一个ip地址我们都可以判断出是否合法有效,但是现在相当于是反向构建合法有效的ip地址,所以我们就是看字符串有多少种合法ipv4的拆分可能。
  • 按照顺序,4段中的每段都可以是1位到3位10进制数,但是不可以有前导0,取值范围是 [0,255]。
  • 去尝试所有的可能,看是否恰好拆分成4段有效值,即正好所有的字符都使用了,并且拆分成了4段有效值。
  • 祭出深度优先,非常强大的递归套娃大法,更准确地说是回溯算法。
  • 注:回溯算法一般需要一个数据结构存储一个临时状态,需要在回溯时还原状态。

题解:

rust:

rust 复制代码
impl Solution {
    pub fn restore_ip_addresses(s: String) -> Vec<String> {
        fn dfs(s: &str, ans: &mut Vec<String>, segments: &mut Vec<String>, seg_start: usize) {
            // 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
            if 4 == segments.len() {
                if seg_start == s.len() {
                    ans.push(segments.join("."));
                }
                return;
            }

            // 一般情况,枚举每一种可能性并递归
            for seg_end in seg_start + 1..=s.len() {
                let segment = &s[seg_start..seg_end];
                if (segment.starts_with('0') && (seg_end - seg_start) > 1) || segment.parse::<usize>().unwrap() > 0xFF {
                    // 有前导零 或者 地址范围大于255
                    break;
                }
                segments.push(segment.to_string());
                dfs(s, ans, segments, seg_end);
                segments.pop();
            }
        }

        let mut ans = Vec::new();

        dfs(s.as_str(), &mut ans, &mut Vec::new(), 0);

        return ans;
    }
}

go:

go 复制代码
func restoreIpAddresses(s string) []string {
    var ans []string

	var dfs func([]string, int)
	dfs = func(segments []string, segStart int) {
		// 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
		if 4 == len(segments) {
			if segStart == len(s) {
				ans = append(ans, strings.Join(segments, "."))
			}
			return
		}

		// 一般情况,枚举每一种可能性并递归
		for segEnd := segStart + 1; segEnd <= len(s); segEnd++ {
			segment := s[segStart:segEnd]
			addr, _ := strconv.ParseInt(segment, 10, 0)
			if (segment[0] == '0' && (segEnd-segStart) > 1) || addr > 0xFF {
				// 有前导零 或者 地址范围大于255
				break
			}
			dfs(append(segments, segment), segEnd)
		}
	}

	dfs([]string{}, 0)

	return ans
}

c++:

cpp 复制代码
class Solution {
private:
    void dfs(const string& s, vector<string>& ans, string segments[], int segIdx, int segStart) {
        // 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
        if (4 == segIdx) {
            if (segStart == s.size()) {
                string addr;
                for (int i = 0; i < 4; ++i) {
                    addr += segments[i];
                    if (i != 3) {
                        addr += '.';
                    }
                }
                ans.emplace_back(addr);
            }
            return;
        }

        // 一般情况,枚举每一种可能性并递归
        for (int segEnd = segStart + 1; segEnd <= s.size(); ++segEnd) {
            string segment = s.substr(segStart, segEnd - segStart);
            if ((segment[0] == '0' && (segEnd - segStart) > 1) || stoi(segment) > 0xFF) {
                // 有前导零 或者 地址范围大于255
                break;
            }
            segments[segIdx] = segment;
            dfs(s, ans, segments, segIdx + 1, segEnd);
        }
    }
public:
    vector<string> restoreIpAddresses(string s) {
        vector<string> ans;
        string segments[4];
        dfs(s, ans, segments, 0, 0);
        return ans;
    }
};

python:

python 复制代码
class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        ans = list()

        def dfs(segments: List[str], seg_start: int):
            # 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
            if 4 == len(segments):
                if seg_start == len(s):
                    ans.append(".".join(segments))
                return

            # 一般情况,枚举每一种可能性并递归
            for seg_end in range(seg_start + 1, len(s) + 1):
                segment = s[seg_start:seg_end]
                if (segment[0] == '0' and (seg_end - seg_start) > 1) or int(segment) > 0xFF:
                    # 有前导零 或者 地址范围大于255
                    break
                segments.append(segment)
                dfs(segments, seg_end)
                segments.pop()

        dfs(list(), 0)
        return ans

java:

java 复制代码
class Solution {
    public List<String> restoreIpAddresses(String s) {
        final List<String> ans = new ArrayList<>();
        dfs(s, ans, new String[4], 0, 0);
        return ans;
    }

    private void dfs(String s, List<String> ans, String[] segments, int segIdx, int segStart) {
        // 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
        if (4 == segIdx) {
            if (segStart == s.length()) {
                ans.add(String.join(".", segments));
            }
            return;
        }

        // 一般情况,枚举每一种可能性并递归
        for (int segEnd = segStart + 1; segEnd <= s.length(); ++segEnd) {
            String segment = s.substring(segStart, segEnd);
            if ((segment.charAt(0) == '0' && (segEnd - segStart) > 1) || Integer.parseInt(segment) > 0xFF) {
                // 有前导零 或者 地址范围大于255
                break;
            }
            segments[segIdx] = segment;
            dfs(s, ans, segments, segIdx + 1, segEnd);
        }
    }
}

非常感谢你阅读本文~

欢迎【点赞】【收藏】【评论】三连走一波~

放弃不难,但坚持一定很酷~

希望我们大家都能每天进步一点点~

本文由 二当家的白帽子:https://le-yi.blog.csdn.net/ 博客原创~


相关推荐
千|寻2 分钟前
【画江湖】langchain4j - Java1.8下spring boot集成ollama调用本地大模型之问道系列(第一问)
java·spring boot·后端·langchain
程序员岳焱15 分钟前
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
后端·sql·mysql
龚思凯21 分钟前
Node.js 模块导入语法变革全解析
后端·node.js
天行健的回响24 分钟前
枚举在实际开发中的使用小Tips
后端
wuhunyu29 分钟前
基于 langchain4j 的简易 RAG
后端
techzhi30 分钟前
SeaweedFS S3 Spring Boot Starter
java·spring boot·后端
aichitang202442 分钟前
矩阵详解:从基础概念到实际应用
线性代数·算法·矩阵
OpenCSG2 小时前
电子行业AI赋能软件开发经典案例——某金融软件公司
人工智能·算法·金融·开源
写bug写bug2 小时前
手把手教你使用JConsole
java·后端·程序员
苏三说技术2 小时前
给你1亿的Redis key,如何高效统计?
后端