题目链接:https://leetcode.com/problems/restore-ip-addresses/
题目:
Given a string containing only digits, restore it by returning all possible valid IP address combinations.
For example:
Given "25525511135"
,
return ["255.255.11.135", "255.255.111.35"]
. (Order does not matter)
思路:
考虑本题和https://leetcode.com/problems/palindrome-partitioning/ 几乎一样,那道题我没做出来,超时了。。。拿过来稍加改动结果AC了。
思路就是,把这道题看成是在1~str.length()之间选择大小为3的子集,我们把该子集作为切分字符串的方案,然后对字符串做相应的切分并判断是否符合ip地址特点。所以本算法分三个部分,子集生成、切分字符串、判断是否符合ip地址的特点。其中子集生成算法实质就是 Combinations
看了别人的题解,发现我的方法虽然思路直观,但实现麻烦,主要是切分字符串要考虑的细节比较多,在实际笔试中可能没那么多时间做出来。
更简洁、值得学习的方法参考 http://blog.csdn.net/linhuanmars/article/details/24683699
算法:
List<String> r = new ArrayList<String>();// 符合ip特点的切分结果
List<List<Integer>> iLists = new ArrayList<List<Integer>>();// 切分方案
List<Integer> list = new ArrayList<Integer>();
String str = "";// 切分字符串用
int length = 0;// 字符串长度
public List<String> restoreIpAddresses(String s) {
this.length = s.length();
if (length > 12 || length < 4) {// ip字符串最大12位,最小4位
return r;
}
this.str = s;
dspPartition(1);// 生成切分方案
cutStr();// 按照生成的切分方案来切分字符串,并判断是否是ip地址
return r;
}
void dspPartition(int cur) { // 这里的切分方案实质是求在[1~k]之间求一个大小为3的子集
if (cur > length) {
return;
} else if (list.size() == 3) { // ip地址有四个部分,3个切分点
iLists.add(new ArrayList<Integer>(list));
} else {
for (int i = cur; i <= length; i++) {
list.add(i);
dspPartition(i + 1);
list.remove(list.size() - 1);
}
}
}
public void cutStr() {
for (int i = 0; i < iLists.size(); i++) {
List<Integer> list = iLists.get(i);
boolean flag = true;
List<String> strs = new ArrayList<String>();// 暂存切分结果
if (list.size() != 0) {
for (int j = 0; j < list.size(); j++) {// 对每种切分方案切分字符串
String tmp = "";
if (j == 0) {// 0~j
tmp = str.substring(0, list.get(j));
if (!isIpNode(tmp)) {
flag = false;
}
strs.add(tmp);
}
if (j - 1 >= 0) {// j-1 ~j
tmp = str.substring(list.get(j - 1), list.get(j));
if (!isIpNode(tmp)) {
flag = false;
}
strs.add(tmp);
}
if (j == list.size() - 1) {// j~~
tmp = str.substring(list.get(j), str.length());
if (!isIpNode(tmp)) {
flag = false;
}
strs.add(tmp);
}
}
}
if (flag) {// 按此种切分方案切分的ip每个部分都满足ip地址特点
String s = "";
for (int d = 0; d < strs.size() - 1; d++) {
s += strs.get(d) + ".";
}
s += strs.get(strs.size() - 1);
r.add(s);
}
}
}
boolean isIpNode(String s) {
if (s.length() > 3) // ip地址长度最大是3位
return false;
if (s.charAt(0) == '0' && s.length() > 1) { // 0开头且长度大于1的字符串是非法的
return false;
}
if (Integer.parseInt(s) <= 255) // ip地址最大为255
return true;
else
return false;
}