题目一:
解法一:(回溯)
解题思路:其实只要意识到这是切割问题,切割问题就可以使用回溯搜索法把所有可能性搜出来
回溯三部曲
- 递归参数
在131.分割回文串 (opens new window)中我们就提到切割问题类似组合问题。
startIndex一定是需要的,因为不能重复分割,记录下一层递归分割的起始位置。
本题我们还需要一个变量pointNum,记录添加逗点的数量。
let result;// 记录结果
// startIndex: 搜索的起始位置,pointNum:添加逗点的数量
const backtracking = function(s, startIndex, pointNum)
- 递归终止条件
终止条件和131.分割回文串 (opens new window)情况就不同了,本题明确要求只会分成4段,所以不能用切割线切到最后作为终止条件,而是分割的段数作为终止条件。
pointNum表示逗点数量,pointNum为3说明字符串分成了4段了。
然后验证一下第四段是否合法,如果合法就加入到结果集里.
- 单层搜索的逻辑
在131.分割回文串 (opens new window)中已经讲过在循环遍历中如何截取子串。
在for (int i = startIndex; i < s.length; i++)循环中 [startIndex, i] 这个区间就是截取的子串,需要判断这个子串是否合法。
如果合法就在字符串后面加上符号.表示已经分割。
如果不合法就结束本层循环,如图中剪掉的分支:
然后就是递归和回溯的过程:
递归调用时,下一层递归的startIndex要从i+2开始(因为需要在字符串中加入了分隔符.),同时记录分割符的数量pointNum 要 +1。
回溯的时候,就将刚刚加入的分隔符. 删掉就可以了,pointNum也要-1。
判断子串是否合法
最后就是在写一个判断段位是否是有效段位了。
主要考虑到如下三点:
- 段位以0为开头的数字不合法
- 段位里有非正整数字符不合法
- 段位如果大于255了不合法
代码随想录中代码:
var restoreIpAddresses = function(s) {
const res = [], path = [];
backtracking(0)
return res;
function backtracking(startIndex) {
console.log('path', path)
const len = path.length;
if(len > 4) return;
if(len === 4 && startIndex === s.length) {
res.push(path.join("."));
return;
}
for(let i = startIndex; i < s.length; i++) {
const str = s.slice(startIndex, i + 1);
if(str.length > 3 || +str > 255) break; // 若当前被截取的子串大于255或者大于三位数,直接结束本层循环
if(str.length > 1 && str[0] === "0") break; // 若数字是0开头,不合法
path.push(str);
backtracking(i + 1);
path.pop()
}
}
};