**剑指 Offer II 087. 复原 IP **【中等题】
思路:
与主站93题重复
93. 复原 IP 地址
【回溯】
这题与一般的回溯法的不同点在于,这题是采用数组存储递归过程中的ip,递归完成之后返回进行其他递归的时候新的数据会把原数组覆盖,因此递归完成之后不用考虑将数组回溯成递归前状态。
思路写在代码注释里,参考自评论区大佬yukiyama
代码:
class Solution {
List<String> list;
int[] ip;
String s;
int n;
public List<String> restoreIpAddresses(String s) {
this.list = new ArrayList<>();
this.ip = new int[4];
this.s = s;
this.n = s.length();
backtrack(0,0);
return list;
}
public void backtrack(int idx,int depth){
if (depth == 4){//depth = 4 递归函数必须返回
if (idx == n){//如果刚好字符串分割完毕,说明找到一个合法的ip地址,将其加入list列表
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++) {
sb.append(ip[i]);
if (i != 3){
sb.append('.');
}
}
list.add(sb.toString());
}
//否则,说明未合法分割,递归函数直接返回
return;
}
//剪枝
//如果剩余待判断字符不足提供剩余ip节数,或者剩余待判断字符超过剩余ip节数的最大字符数,函数直接返回
if (n - idx < 4 - depth || n - idx > (4 - depth) * 3){
return;
}
//计算当前待分段ip的值
int seg = 0;
for (int i = idx; i < idx + 3 && i < n; i++) {
seg = seg * 10 + (s.charAt(i)-'0');
//剪枝
//ip分段合法性检查 如果当前分段ip不合法,当前层的递归函数直接终止
if (seg > 255 || seg < 0){
return;
}
//ip分段通过合法性检查后,将其存入ip数组
ip[depth] = seg;
//从i+1位开始继续检查ip分段,此时ip分段检查的深度+1
backtrack(i+1,depth+1);
//如果当前ip分段是0 那么它只能作为单独的一节,当前递归直接返回,不必再考察后边的i
//(递归函数每次只判断一个ip分段,ip分段合法则任务完成,因此需要直接返回)
if (seg == 0){
return;
}
}
}
}
剑指 Offer II 088. 爬楼梯的最少成本【简单题】
思路:【动态规划】
见代码注释。
代码:
class Solution {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
//dp数组用来存储到达第i个位置的花费,根据题目规则,最后一步可能刚好跳到最后一级台阶,也可能跳到最后一级台阶的上面,因此dp的长度为n+1
int[] dp = new int[n+1];
for (int i = 2; i <= n; i++) {
//动态转移公式如下:
//到达第i个位置的花费 = min{到达第i-1位置的花费dp[i-1]+在第i-1位置跳一级台阶达到第i个位置的花费cost[i-1] , 到达第i-2位置的花费dp[i-2] + 在第i-2位置跳两级台阶到达第i个位置的花费 cost[i-2] }
dp[i] = Math.min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
//我们只需跳到最后一级
return dp[n];
}
}