c语言递归算法求恢复ip地址,回溯算法之复原IP地址

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

百度百科说的有点晦涩,就是递归算法,但是有要注意的点:

保留现场,在进行递归的时候,保存上一次的状态,递归回来之后仍然能回到上次的状态

结束条件,满足条件的时候保存结果

题目

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

示例:

输入: "25525511135"

输出: ["255.255.11.135", "255.255.111.35"]

解答

我做的算法题不多,但是个人经验,在做题的时候最好能手动的在纸上画图,模拟程序运行的图。

一张大白纸

认真的画图

不过也可能再电脑上画图会更方便,我们先思考程序的运行大致应该是什么路径。如图:

3fff7d68b965

image-20190319081953592

限定条件:

因为是IP地址,所以有一定的条件限制,数字不能大于255,不能小于0

在图上可以看出来,得出是否是IP地址的在第3层。

先想到大概的变量。

层级

当前的字符串

剩余的字符串

保存结果的集合

写出终止递归的条件

private void restoreAddressNew(String source, String currentStr, Integer currentLevel, Integer offset, List res) {

if (currentLevel == 3) {

if (isValidNew(source.substring(offset))

) {

res.add(currentStr + "." + source.substring(offset));

}

return;

}

....

}

写出校验是否合法IP中段位的函数

private boolean isValidNew(String str) {

if (str.length() == 0 || str.length() > 3 || Integer.parseInt(str) < 0 || Integer.parseInt(str) > 255

|| (str.startsWith("0") && str.length() > 1)

) {

return false;

}

return true;

}

写进行递归的条件

private void restoreAddressNew(String source, String currentStr, Integer currentLevel, Integer offset, List res) {

if (currentLevel == 3) {

if (isValidNew(source.substring(offset))

) {

res.add(currentStr + "." + source.substring(offset));

}

return;

}

// 递归段

for (int i = 1; i <= 3; i++) {

if (offset > source.length() || (offset + i) > source.length()) {

return;

}

String seg = source.substring(offset, offset + i);

// 用于保存原先的状态

String oldStr = currentStr;

// 防止出现以 "."开头的地址

if (currentStr.length() == 0) {

currentStr = seg;

} else {

currentStr = currentStr + "." + seg;

}

if (isValidNew(seg)) {

restoreAddressNew(source, currentStr, currentLevel + 1, offset + i, res);

// 处理完之后恢复状态

currentStr = oldStr;

}

}

}

如果有不确定的地方,在其中可以输出当前的状态,判断当前的结果

完整的方案

public class RestoreIPAddress {

public static void main(String[] args) {

List strings = new RestoreIPAddress().restoreIpAddressesNew("25525511135");

}

private List restoreIpAddressesNew(String s) {

List result = new ArrayList<>();

restoreAddressNew(s, "", 0, 0, result);

return result;

}

private void restoreAddressNew(String source, String currentStr, Integer currentLevel, Integer offset, List res) {

if (currentLevel == 3) {

if (isValidNew(source.substring(offset))

) {

res.add(currentStr + "." + source.substring(offset));

}

return;

}

for (int i = 1; i <= 3; i++) {

if (offset > source.length() || (offset + i) > source.length()) {

return;

}

String seg = source.substring(offset, offset + i);

String oldStr = currentStr;

if (currentStr.length() == 0) {

currentStr = seg;

} else {

currentStr = currentStr + "." + seg;

}

if (isValidNew(seg)) {

restoreAddressNew(source, currentStr, currentLevel + 1, offset + i, res);

currentStr = oldStr;

}

}

}

private boolean isValidNew(String str) {

if (str.length() == 0 || str.length() > 3 || Integer.parseInt(str) < 0 || Integer.parseInt(str) > 255

|| (str.startsWith("0") && str.length() > 1)

) {

return false;

}

return true;

}

}

中间犯的错误

第一次忘了保存现场,就会出现”数据打架“,数据很奇怪

出现过"."开头的地址情况

都是想问题不够全面导致的,程序运行的快,人算的慢,但是程序运行的规则是人定义的。只有自己能想清楚规则,才能指导计算机做正确的事情,否则当自己都迷糊的时候,程序怎么可能运行的正确。

最后

画图是的个好东西,帮你理清思路,慢慢来,不要着急

参考

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值