Leetcode-Restore IP Addresses

问题描述(摘抄自LeetCode):

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://oj.leetcode.com/problems/restore-ip-addresses/
问题解析:

   本算法要求实现:将给定的数字字符串解析为有效的IP地址的格式(点分十进制),而且不要求结果的顺序。首先我们来分析一下IP地址的格式,看一下有什么规律?我们知道IP地址实质上由四个字节组成,但是为了阅读方便,通常采用点分十进制的形式,也就是说:每个字节的有效范围为:0-255(包括0和255);相邻两个字节中间插入一个点字符来分割。

   知道了IP地址的形式,这个算法就好实现了。笔者首先想到的是用多层循环来实现,实质上要想实现分割,只需要确定好三个小数点的位置即可,但是有三种情况尤其需要注意:前置0的情况一定要排除,譬如:01.1.1.1、1.021.3.4;字节范围超出255的要去除,如:12.256.234.21。因此我专门写了个验证各字节的数据是否有效的函数,来处理这两种情况,还有一点就是C++里是没有直接转化为int的方法的,因此这个方法也需要自己来写。通过以上分析,代码自然就出来了,我的解决方案如下:

class Solution {
public:
    int stringToInt(string s)   //字符串转化为数字
    {
        int length = s.size();
        int sum = 0;
        int i = 0;
        while (i < length)
        {
            sum = sum * 10 + s[i] - '0';
            i++;
        }
        return sum;
    }
    bool isValid(string s1)     //数据有效性验证
    {
        if (s1[0] == '0' && s1 != "0")
        {
            return false;
        }
        if(stringToInt(s1) > 255)
        {
            return false;
        }
        return true;
    }
    vector<string> restoreIpAddresses(string s) {
        int len = s.size();
        vector<string> result;
        if (len < 4 || len > 12)
        {
            return result;
        }
        int i, j, k;
        for (i = 1; i <= 3; i++)
            for (j = i + 1; j - i <= 3; j++)
                for (k = j + 1; (k - j <= 3) && (k < len); k++)
                {
                    string temp = "";
                    if (len - k > 3)
                    {
                        continue;
                    }
                    if (!isValid(s.substr(0, i)) || !isValid(s.substr(i, j-i)) || !isValid(s.substr(j, k-j)) || !isValid(s.substr(k, len-k)))
				    {
					    continue;
				    }
				    temp = s.substr(0, i) + "." + s.substr(i, j-i) + "." + s.substr(j, k-j) + "." + s.substr(k, len-k);
				    result.push_back(temp);
                } 
        return result;
    }
};

结果分析:    

   那么笔者的解决方案能否通过呢,答案是肯定的,通过下面系统给出的结果分析可以看出,运行时间仅为36ms,也算是对自己努力半天的回报吧。

其他实现思路:

   上面笔者给出了循环的方案,那么还有没有其他方式,当然有了,还有一种常见的方法就是使用递归来解决,不过时间会有点久的,有兴趣的可以研究一下啊。

  Python解决方案:

    下面我们给出相应方案的python代码,因为python里面的变量是无类型的,所以整型和字符串可以很方面的转换,还有就是python自带的字符串分割功能,所以python代码的形式会非常简单,解决方案如下:

class Solution:
    # @param s, a string
    # @return a list of strings
    def isValid(self, l):
        for li in l:
            if li[0] == "0" and li != "0":
                return False;
            elif int(li) > 255:
                return False;
        return True;
    def restoreIpAddresses(self, s):
        length = len(s);
        result = [];
        
        for i in [1, 2, 3]:
            for j in [i+1, i+2, i+3]:
                for k in [j+1, j+2, j+3]:
                    if k >= length:
                        continue;
                    if self.isValid([s[:i], s[i:j], s[j:k], s[k:]]):
                        result.append(s[:i] + "." + s[i:j] + "." + s[j:k] + "." + s[k:]);
        return result;


   虽然说python的代码写起来非常容易,而且形式也简单,相同算法的代码长度通常都比C++要简短,但是通过系统的结果分析,我们也可以看出,同样是测试了147个案例,C++只用了32ms,而python却用了228ms。AC结果如下:


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值