93. 复原 IP 地址

1,556 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情

题目描述

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

截屏2022-04-28 下午9.22.38.png

思路描述

关键条件只包含数字的字符串。

在这个前提下这道题其实就是分成两部分,第一部分是分割字符串,第二部分是判断字符串的合法行。

我们可以用dfs解决这个问题

代码整体分为几部分

  • 达成条件-》加入结果数组
  • 达成失败 return
  • 截取下一段

需要注意的是,由于不存在前导0的问题,因此遇到0就直接dfs

具体实现

void dfs(const string& s, int segId, int segStart) {
        if (segId == SEG_COUNT) {
            if (segStart == s.size()) {
                string ipAddr;
                for (int i = 0; i < SEG_COUNT; ++i) {
                    ipAddr += to_string(segments[i]);
                    if (i != SEG_COUNT - 1) {
                        ipAddr += ".";
                    }
                }
                ans.push_back(move(ipAddr));
            }
            return;
        }

        if (segStart == s.size()) {
            return;
        }

        if (s[segStart] == '0') {
            segments[segId] = 0;
            dfs(s, segId + 1, segStart + 1);
        }

        int addr = 0;
        for (int segEnd = segStart; segEnd < s.size(); ++segEnd) {
            addr = addr * 10 + (s[segEnd] - '0');
            if (addr > 0 && addr <= 0xFF) {
                segments[segId] = addr;
                dfs(s, segId + 1, segEnd + 1);
            } else {
                break;
            }
        }
    }

总结

这道题并不一定要使用回溯,理论上写四层甚至三层for循环也可以实现(因为最后一层一定使用剩下所有的字符。)