开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第27天,点击查看活动详情
前言
算法的重要性不言而喻!区分度高!
现在学习的门槛低了,只有能上网每个人都可以学编程!培训班6个月就可以培养出来能干活的人,你怎么从这些人中脱颖而出?没错!就是学算法,学一些底层和基础的东西。
说的功利点是为了竞争,卷死对手。真心话说就是能提高自己的基础能力,为技术可持续发展做好充分的准备!!!
提前入门学习书籍:CPrimerPlus、大话数据结构
刷题网站
我是按照代码随想录提供的刷题顺序进行刷题的,大家也可以去刷leetcode最热200道,都可以
刷题嘛,最重要的就是坚持了!!!
画图软件
OneNote
这个要经常用,遇见不懂的流程的话就拿它画一画!
笔记软件
Typoral
题目
解析
复原IP地址和切割问题类似,只不过它有很多条件要注意,就是IP地址的规范 比如:IP段不能超过4段,每段的数字必须小于256
除此之外,题目要求,地址之间通过点来联系,所以我们还需要一个ponitNum来记录逗点的数量
回溯三部曲
- 递归参数
递归的参数中,start是必须的,因为不能重复切割,他负责遍历的时候我们应该从哪里进行切割
String s为目标字符串
number为ip段的数量
public void restoreIpAddressesHandler(String s, int start, int number) {}
- 递归终止的条件
-
如果start等于s的长度并且ip段的数量是4,则加入结果集,并返回
-
如果start等于s的长度但是ip段的数量不为4,或者ip段的数量为4但是start小于s的长度,则直接返回
if (start == s.length() && number == 4) {
result.add(stringBuilder.toString());
return;
}
if (start == s.length() || number == 4) {
return;
}
- 单层搜索的逻辑
-
substring() 方法返回字符串的子字符串
-
也就是在这个循环里,把所有可能的情况都包含进去了,比如ip段最大长度为3,每段处于0,255
-
ip段的长度最大是3,对应的代码就是i - start < 3
-
ip段的处于[0,255],对应的条件就是Integer.parseInt(s.substring(start,i+1))>=0,Integer.parseInt(s.substring(start, i + 1)) <= 255
-
终止循环的条件就为i < s.length(),也就是说把传进来的字符串遍历完了
-
如果ip段的长度大于1,并且第一位为0的话,continue。因为ip段中的第一段不能为0
-
当stringBuilder里的网段数量小于3时,才会加点;如果等于3,说明已经有3段了,最后一段不需要再加点
for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0 && Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) {
if (i + 1 - start > 1 && s.charAt(start) - '0' == 0) {
continue;
}
stringBuilder.append(s.substring(start, i + 1));
if (number < 3) {
stringBuilder.append(".");
}
number++;
restoreIpAddressesHandler(s, i + 1, number);
number--;
// 删除当前stringBuilder最后一个网段,注意考虑点的数量的问题
stringBuilder.delete(start + number, i + number + 2);
}
}
完整代码
其实完整做下来还是有点难度的,没什么办法,多理解,多刷才行
//方法二:比上面的方法时间复杂度低,更好地剪枝,优化时间复杂度
class Solution {
// 存放结果
List<String> result = new ArrayList<String>();
// 拼接字符串
StringBuilder stringBuilder = new StringBuilder();
public List<String> restoreIpAddresses(String s) {
restoreIpAddressesHandler(s, 0, 0);
return result;
}
// number表示stringbuilder中ip段的数量
public void restoreIpAddressesHandler(String s, int start, int number) {
// 如果start等于s的长度并且ip段的数量是4,则加入结果集,并返回
if (start == s.length() && number == 4) {
result.add(stringBuilder.toString());
return;
}
// 如果start等于s的长度但是ip段的数量不为4,或者ip段的数量为4但是start小于s的长度,则直接返回
if (start == s.length() || number == 4) {
return;
}
// 剪枝:ip段的长度最大是3,并且ip段处于[0,255]
//substring() 方法返回字符串的子字符串。
//也就是在这个循环里,把所有可能的情况都包含进去了,比如ip段最大长度为3,每段处于0,255
// ip段的长度最大是3,对应的代码就是i - start < 3
// ip段的处于[0,255],对应的条件就是Integer.parseInt(s.substring(start,i+1))>=0,Integer.parseInt(s.substring(start, i + 1)) <= 255
// 终止循环的条件就为i < s.length(),也就是说把传进来的字符串遍历完了
for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0 && Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) {
// 如果ip段的长度大于1,并且第一位为0的话,continue。因为ip段中的第一段不能为0
if (i + 1 - start > 1 && s.charAt(start) - '0' == 0) {
continue;
}
//拼接
stringBuilder.append(s.substring(start, i + 1));
// 当stringBuilder里的网段数量小于3时,才会加点;如果等于3,说明已经有3段了,最后一段不需要再加点
if (number < 3) {
stringBuilder.append(".");
}
number++;
restoreIpAddressesHandler(s, i + 1, number);
number--;
// 删除当前stringBuilder最后一个网段,注意考虑点的数量的问题
stringBuilder.delete(start + number, i + number + 2);
}
}
}