【LeetCode每日一题】(8.9)复原IP地址(回溯)

时间:2022-07-23
本文章向大家介绍【LeetCode每日一题】(8.9)复原IP地址(回溯),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

复原IP地址

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 ‘.’ 分隔。

示例:

输入: "25525511135"
输出: ["255.255.11.135", "255.255.111.35"]

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

思路

这题之前做过,不过上次做的一头雾水。 现在一看就知道是回溯了。

做第一步时我们有几种 选择 ?以 “25525511135” 为例:

选 "2" 作为第一个片段 选 "25" 作为第一个片段 选 "255" 作为第一个片段

每次有三种选择,做了选择后,又面临三种选择:切出一种长度的片段作为第二个片段。 这会像树一样向下分支,我们用 DFS 去遍历所有选择,并且是回溯,为什么是回溯? 因为你每一步选择可能累积生一个错误结果,这时要撤销最后一个选择,去试探另一个选择。 穷举出所有可能,才能找出所有组合。好,我们现在讲完 回溯的第一个要点——选择。

回溯的第二个要点——约束

这道题的约束条件是: 一个片段的长度是 1~3 片段的值范围是 0~255 不能是 "0x"、"0xx" 形式(这个是测试用例告诉我们的) 这些约束都将应用在我们的 DFS 函数中,达到剪枝的效果。

回溯的第三个要点——目标

我们目标决定了我们的 DFS 什么时候捕捉答案,什么时候该砍掉死支(然后回溯)。 我们目标是生成 4 个有效片段,并且我们要用光 IP 字符串的字符。 当遍历的节点满足该条件时,说明生成了一个有效组合,推入结果数组。 生成了4个有效片段,但没用过所有字符,则不往下递归,选择回溯。

定义dfs函数

dfs函数传什么,用什么代表不同节点的状态? 选择切出一个长度的片段后,剩余的子串继续递归,我们可以用指向剩余子串起始位置的指针,加上当前已经生成的片段数组,作为状态,传入 dfs 函数。 dfs 函数做的是「复原从指针 start 开始的子串」。

代码实现

 	vector<string> restoreIpAddresses(string s, int index)
    {
        vector<string> vip;
        if (index == 3) {
            if (s.size() == 0 || s.size() > 3 || (s.size() > 1 && s[0] == '0'))
                return vip;
            int val = atoi(s.c_str());
            if (val >= 0 && val <= 255) {
                vip.push_back(s);
            }
            return vip;
        } else {
            for (int i = 1; i < 4 && i <= s.size(); i++) {
                string tmp = s.substr(0, i);
                if (i > 1 && s[0] == '0')
                    continue;
                int val = atoi(tmp.c_str());
                if (val >= 0 && val <= 255) {
                    vector<string> nextv = restoreIpAddresses(s.substr(i), index+1);
                    for (int k = 0; k < nextv.size(); ++k) {
                        string ip(tmp);
                        ip.append(".").append(nextv[k]);
                        vip.push_back(ip);
                    }
                }
            }
        }
        return vip;
    }
    
    vector<string> restoreIpAddresses(string s) {
        return restoreIpAddresses(s, 0);
    }