“给定一个只包含整数的字符串,表示一个IP地址,返回所有可能有效的IP地址,在这些地址中插入点来形成。”
题目链接:
来源:力扣(LeetCode)
链接:93. 复原 IP 地址 - 力扣(LeetCode) (leetcode-cn.com)
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
示例 1:
输入: s = "25525511135"
输出: ["255.255.11.135","255.255.111.35"]
示例 2:
输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
找出所有可能的IP地址,可以考虑使用回溯的方法,对所有的字符串进行分割筛选,找到满足要求的所有答案。
首先从开始位置开始,从IP地址每一段进行分析,由于IP地址的每一段必须是0-255的整数,那么就枚举这一段IP地址,如果满足要求就进行下一段的搜索,然后调用递归函数。
代码参考:
class Solution {
static final int SEG_COUNT = 4;
List<String> ans = new ArrayList<String>();
int[] segments = new int[SEG_COUNT];
public List<String> restoreIpAddresses(String s) {
segments = new int[SEG_COUNT];
dfs(s, 0, 0);
return ans;
}
public void dfs(String s, int segId, int segStart) {
// 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
if (segId == SEG_COUNT) {
if (segStart == s.length()) {
StringBuffer ipAddr = new StringBuffer();
for (int i = 0; i < SEG_COUNT; ++i) {
ipAddr.append(segments[i]);
if (i != SEG_COUNT - 1) {
ipAddr.append('.');
}
}
ans.add(ipAddr.toString());
}
return;
}
// 如果还没有找到 4 段 IP 地址就已经遍历完了字符串,那么提前回溯
if (segStart == s.length()) {
return;
}
// 由于不能有前导零,如果当前数字为 0,那么这一段 IP 地址只能为 0
if (s.charAt(segStart) == '0') {
segments[segId] = 0;
dfs(s, segId + 1, segStart + 1);
}
// 一般情况,枚举每一种可能性并递归
int addr = 0;
for (int segEnd = segStart; segEnd < s.length(); ++segEnd) {
addr = addr * 10 + (s.charAt(segEnd) - '0');
if (addr > 0 && addr <= 0xFF) {
segments[segId] = addr;
dfs(s, segId + 1, segEnd + 1);
} else {
break;
}
}
}
}
用COUNT=4表示IP地址的段数。
时间复杂度 : O(3COUNTX |s|)
由于IP地址每一段的位数不会超过3,因此递归最多三层,那么时间复杂度就是O(3COUNT),如果复原出了一种满足题目要求的IP地址,那么还需要O(|s|)的时间加入到时间复杂度中。
空间复杂度: O(COUNT)
只计入存储答案的数组以外的额外空间复杂度,因此空间复杂度为O(COUNT)。
这道题就是一个深度优先遍历的问题。
通过遍历每一段IP地址来判断是否满足要求,来一层层的去找到满足题意的答案。