复原ip地址--回溯算法

LeetCode

复原IP地址

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

有效的IP地址正好由四个整数(每个整数位于0255之间组成),整数之间用'.'分隔。

示例:

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

解法:回溯法

解题思路:给定一个字符串,要我们找到可能IP地址格式,首先,根据IP地址格式,我们先将不符合条件的直接返回

List res= new ArrayList<>();
int len = s.length();
if(len<4 || len>12) //最少需要四个数字,最多不超过12个数字
    return res;

现在,我们想通过回溯法来解决问题,首先就需要明确,回溯的思路是如何的?

首先,我们要做的就是将IP地址的四个数字给找出来,我们先找到第一个数字,然后在第一个数字的基础上,我们再找第二个数字,依次类推,当我们找到最后一个数字时,发现字符串还有剩余,或者,我们还没找完四个数字,字符串就已经没了,这时候我们知道了,这种组合是错误的,因此,我们会进行回溯,也就是回到找第四个数字的那一步,当第四个数字的所有可能都找完时,我们就回到第三个数字,依次类推

因此,我们使用递归来解决这个问题,由上可知,递归出口为:

if(point>3) //我们用point来表示IP地址中的点,当超过3个点时,说明四个数字都找完了
{
    if(begin==len) //如果刚好字符串完了,就说明这个组合是成立的,将其加入结果集中
    {
        ip.delete(ip.length()-1, ip.length());
        res.add(ip.toString());
    }     
    return;
}
else //数字还没找完
    if(begin==len) //但是字符串却没了,说明是错误的,直接返回
        return;

现在,我们来看数字的可能组合,因为大小为0-255,所以,数字的位数为1-3位

for(int i=1; i<=3; i++) //表示数字的位数
{
    if(i>len-begin) //如果位数超过了字符串剩余的长度,说明不可行
    {
        break;
    }  
    String piece = (String) s.subSequence(begin, begin+i); //从字符串中提取出我们需要的数字
    int val = Integer.valueOf(piece).intValue(); //将其转换为int类型
    if(val>255) //大于255直接退出循环
        break;
    else if((val<10&&i>1)||(val<100&&i>2)) //这一行代码是为了避免010 01等数字情况
        break;
    ip.append(piece+"."); //在后面加个.
    dfs(res,s,begin+i,len,ip,point+1); //找下一个数字
    ip.delete(begin+point, point+begin+i+1); //删除刚才加入的数字,进行回溯,因为加了.(点),所以要加上偏移point
}

完整代码:

/*
s是输入的字符串
len是字符串的长度
res是结果集
ip是每一个符合地址格式的可扩展字符串,长度为len+3
point表示格式中点的个数
begin表示字符的起始位置,因为前面用到的后面不能再用
*/
public List restoreIpAddresses(String s) {
    List res= new ArrayList<>();
    int len = s.length();
    if(len<4 || len>12)
        return res;
    
    StringBuilder ip = new StringBuilder(len+3);
    dfs(res,s,0,len,ip,0);
    
    return res;        
}
public void dfs(List res, String s, int begin, int len, StringBuilder ip, int point)
{
    if(point>3)
    {
        if(begin==len)
        {
        	ip.delete(ip.length()-1, ip.length());
        	res.add(ip.toString());
        }
            
        return;
    }
    else
        if(begin==len)
            return;
    for(int i=1; i<=3; i++)
    {
        if(i>len-begin)
        {
        	continue;
        }  
        String piece = (String) s.subSequence(begin, begin+i);
        int val = Integer.valueOf(piece).intValue();
        if(val>255)
        	break;
        else if((val<10&&i>1)||(val<100&&i>2))
        	break;
        ip.append(piece+".");
        dfs(res,s,begin+i,len,ip,point+1);
        ip.delete(begin+point, point+begin+i+1);
    }
    return; 
}

心得体会

这一道题是我自己做出来的,做算法题的时候经常会做不出来必须得看答案,但是,我觉得看答案只要看的懂,懂的它的思想,我觉得一样是有收获的,不然我也不能独立完成这道题,这道题虽然过了,然而效率不是很高,以我现在的水平,要进行优化很难,这时候还是得去看别人的题解,我觉得看别人题解也是一种很有效的学习方法

你可能感兴趣的:(回溯算法)