合法IP的数量

来源:互联网 发布:数据库查找编写的代码 编辑:程序博客网 时间:2024/05/01 18:13

题目

给定一个全是数字的字符串,返回可以转成合法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段数量大于了4return 0;}if (i == chas.length) {//当前位置达到了字符数组的最后位置,如果此时已经形成的ip段是4则返回1,否则返回0return parts == 4 ? 1 : 0;}int res = process(chas, i + 1, parts + 1);//递归调用。下一个位置,已形成的ip段+1if (chas[i] == '0') {//如果当前字符是0,为了使ip段合法(不出现以0开头的ip段),返回前面已形成的ip段数量return res;}res += process(chas, i + 2, parts + 1);//当前位置不为0的情况下,当前位置可以向后跳动2个位置,同时已形成的ip段+1if (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];}