合法IP的数量

题目

给定一个全是数字的字符串,返回可以转成合法IP的数量

示例

例如:101111
可以转成:
1.0.1.111, 1.0.11.11, 1.0.111.1
10.1.1.11, 10.1.11.1, 10.11.1.1
101.1.1.1
所以返回7

分析:每一个IP由4段组成,每一个小段的数字在0-255之间,并且每一个小段不能有以0开始的长度不是1的段,即不能出现.012.类似的IP段

首先使用递归函数实现

public static int convertNum1(String str) {
	if (str == null || str.length() < 4 || str.length() > 12) {//字符串的长度必须在4到12之间
		return 0;
	}
	char[] chas = str.toCharArray();
	return process(chas, 0, 0);//在第0个位置的时候形成的ip数量是0个
}

//chas:字符串转换成的字符数组
//i:当前位置
//parts:已经形成的ip段数目
public static int process(char[] chas, int i, int parts) {
	if (i > chas.length || parts > 4) {//当前位置超过了字符数组的最终位置或者已经形成的ip段数量大于了4
		return 0;
	}
	if (i == chas.length) {//当前位置达到了字符数组的最后位置,如果此时已经形成的ip段是4则返回1,否则返回0
		return parts == 4 ? 1 : 0;
	}
	int res = process(chas, i + 1, parts + 1);//递归调用。下一个位置,已形成的ip段+1
	if (chas[i] == '0') {//如果当前字符是0,为了使ip段合法(不出现以0开头的ip段),返回前面已形成的ip段数量
		return res;
	}
	res += process(chas, i + 2, parts + 1);//当前位置不为0的情况下,当前位置可以向后跳动2个位置,同时已形成的ip段+1
	if (i + 2 < chas.length) {
		int sum = (chas[i] - '0') * 100 + (chas[i + 1] - '0') * 10 + (chas[i + 2] - '0');
		if (sum < 256) {//保证行成的ip段范围是0-255之间
			return res + process(chas, i + 3, parts + 1);//如果在此范围内,当前位置可以向后跳动三个位置
		} else {
			return res;
		}
	} else {
		return res;
	}
}
优化之后的动态规划实现

public static int convertNum2(String str) {
	if (str == null || str.length() < 4 || str.length() > 12) {
		return 0;
	}
	char[] chas = str.toCharArray();
	int size = chas.length;
	int[][] dp = new int[size + 3][5];
	dp[size][4] = 1;
	for (int parts = 3; parts >= 0; parts--) {
		for (int i = size - 1; i >= parts; i = Math.min(i - 1, parts * 3)) {
			dp[i][parts] = dp[i + 1][parts + 1];
			if (chas[i] != '0') {
				dp[i][parts] += dp[i + 2][parts + 1];
				if (i + 2 < chas.length) {
					int sum = (chas[i] - '0') * 100 + (chas[i + 1] - '0') * 10 + (chas[i + 2] - '0');
					if (sum < 256) {
						dp[i][parts] += dp[i + 3][parts + 1];
					}
				}
			}
		}
	}
	return dp[0][0];
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值