• 93. 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)

    链接: http://leetcode.com/problems/restore-ip-addresses/

    题解:

    这道题也卡了一段时间。也可以用DFS + Backtracking来解决。第二遍的时候需要多思考多加练习。

    Time Complexity - O(2n), Space Complexity - O(2n)

    public class Solution {
        public List<String> restoreIpAddresses(String s) {
            List<String> res = new ArrayList<>();
            if(s == null || s.length() < 4 || s.length() > 12)
                return res;
            ArrayList<String> list = new ArrayList<>();
            restoreIpAddresses(res, list, s, 0);
            return res;
        }
        
        private void restoreIpAddresses(List<String> res, ArrayList<String> list, String s, int pos) {
            if(list.size() == 4) {
                if(pos != s.length())
                    return;
                StringBuilder sb = new StringBuilder();
                for(String tmp : list) {
                    sb.append(tmp);
                    sb.append(".");
                }
                sb.setLength(sb.length() - 1);
                res.add(sb.toString());
                return;
            }
            
            for(int i = pos; i < s.length() && i <= pos + 3; i++) {
                String tmp = s.substring(pos, i + 1);
                if(isIpValid(tmp)) {
                    list.add(tmp);
                    restoreIpAddresses(res, list, s, i + 1);
                    list.remove(list.size() - 1);
                }
            }
        }
        
        private boolean isIpValid(String s) {
            if(s == null || s.length() == 0)
                return false;
            if(s.charAt(0) == '0')
                return s.equals("0");
            int ip = Integer.parseInt(s);
            if(ip <= 255 && ip >= 0)
                return true;
            return false;
        }
    }

    另外还有一种做法是用3个for loop来把整个字符串切成4段。参见discussion

    二刷:

    代码比较长,比较难写对。总的来说还是使用dfs + backtracking。 要注意dfs的时候先判断segment = s.substring(pos, i + 1)是否valid,然后再进行dfs和回溯。时间复杂度和空间复杂度还不确定。

    Java:

    Time Complexity - O(2n), Space Complexity - O(2n)

    public class Solution {
        public List<String> restoreIpAddresses(String s) {
            List<String> res = new ArrayList<>();
            if (s == null || s.length() < 4 || s.length() > 12) {
                return res;
            }
            List<String> ipAddress = new ArrayList<>();
            restoreIpAddresses(res, ipAddress, s, 0);
            return res;
        }
        
        private void restoreIpAddresses(List<String> res, List<String> ipAddress, String s, int pos) {
            if (ipAddress.size() == 4) {
                if (pos != s.length()) {
                    return;
                }
                StringBuilder sb = new StringBuilder();
                for (String str : ipAddress) {
                    sb.append(str);
                    sb.append(".");
                }
                sb.setLength(sb.length() - 1);
                res.add(sb.toString());
                return;
            }
            for (int i = pos; i < s.length() && i < pos + 3; i++) {
                String segment = s.substring(pos, i + 1);
                if (isValidIP(segment)) {
                    ipAddress.add(segment);
                    restoreIpAddresses(res, ipAddress, s, i + 1);
                    ipAddress.remove(ipAddress.size() - 1);
                }
            }
        }
        
        private boolean isValidIP(String s) {
            if (s == null || s.length() == 0) {
                return false;
            }
            if (s.charAt(0) == '0') {
                return s.equals("0");
            }
            int ip = Integer.parseInt(s);
            if (ip <= 255 && ip >= 0) {
                return true;
            }
            return false;
        }
    }

    三刷:

    Restore IP Addresses。这道题有不少小细节,不好写但是很有意思。 我们主要把这道题目分成三个部分。

    1. 题目给定的restoreIpAddresses方法
      1. 这里我们首先确定要用到递归 + 回溯。 并且我们要了解,合理的ipv4地址是由4段组成,而且每一段的值都在 [0 , 255] 之间
      2. 在这个方法里面,我们要做一些基本的边界判断,比如s 是否为null, s的length 是否在 4 和 12之间。
      3. 构造好用来递归求解的方法restoreIp,确定好每个要用的参数。
      4. 返回结果
    2. restoreIp方法
      1. 这个方法是我们主要进行处理和判断的方法。我们也分为两个部分
      2. 判断并返回结果:
        1. 当我们用来保存ip地址List<String> ip长度已经等于4的时候
          1. 我们判断记录当前position的int pos是否正好等于String s的长度, 假如否,我们返回
          2. 否则,这时我们找到一个合理的解。可以建立一个StringBuilder ipSb,重建出这个ip address,将其加入结果集 res中,返回
      3. 递归求解:
        1. 这里我们要从i = pos, 到i < s.length() && i < pos + 3来进行遍历。 因为ip每一部分最多只有3个digit,所以我们有这个pos + 3的constraint
          1. 每次先求得当前的ip segment = s.substring(i, pos + 1)
          2. 接下来进行判断, 调用isIpValid方法
            1. 假如当前ip segment合理, 我们将这段ip segment加入到list ip中
            2. 递归调用restoreIp(res, list, s, i + 1)进行下一步求解
            3. 进行回溯,去除掉之前加入的这段ip segment
          3. 否则我们增加i,继续尝试下一个ip segment, 直到i = pos + 3时跳出循环
    3. isIpValid方法
      1. 这个方法主要用来确定ip segment是否合理
        1. 首先s为null或者""的时候返回false
        2. 当s的首字符为'0'的时候,我们要判断是否整个s为"0"。 假如是,我们返回true, 假如否,那么这次切割结果"0x"不合理,我们返回false
        3. 求出ip segment的int值,然后返回这个 ipInt是否 >= 0 并且 <= 255
    4. 粗略的时间和空间复杂度估计为O(2n),但因为有很多的剪枝,有substring(),而且n的范围是在4和12之间,所以详细复杂度并不高,但也并不好算。

    Java:

    Time Complexity - O(2n), Space Complexity - O(2n)

    public class Solution {
        public List<String> restoreIpAddresses(String s) {
            List<String> res = new ArrayList<>();
            if (s == null || s.length() < 4 || s.length() > 12) return res;
            restoreIp(res, new ArrayList<>(), s, 0);
            return res;
        }
        
        private void restoreIp(List<String> res, List<String> ip, String s, int pos) {
            if (ip.size() == 4) {
                if (pos != s.length()) return;
                StringBuilder ipSb = new StringBuilder();
                for (String str : ip) ipSb.append(str).append(".");
                ipSb.setLength(ipSb.length() - 1);
                res.add(ipSb.toString());
                return;
            }
            
            for (int i = pos; i < s.length() && i < pos + 3; i++) {
                String ipSeg = s.substring(pos, i + 1);
                if (isIpValid(ipSeg)) {
                    ip.add(ipSeg);
                    restoreIp(res, ip, s, i + 1);
                    ip.remove(ip.size() - 1);
                }
            }
        }
        
        private boolean isIpValid(String s) {
            if (s == null || s.length() == 0) return false;
            if (s.charAt(0) == '0') return s.equals("0");
            int ipInt = Integer.parseInt(s);
            return ipInt >= 0 && ipInt <= 255;
        }
    }

    Reference:

    https://leetcode.com/discuss/19296/my-concise-ac-java-code

    https://leetcode.com/discuss/12790/my-code-in-java

    https://leetcode.com/discuss/15098/very-simple-dfs-solution

    https://leetcode.com/discuss/27481/java-concise-recursion-solution

    https://leetcode.com/discuss/48726/easy-java-code-of-backtracking-within-16-lines

  • 相关阅读:
    无法访问计算机XXXX。错误是:库没有注册。
    Unix网卡重启命令
    教你如何进入有密码的 XP 系统
    巧妙恢复被破坏的Windows XP系统文件
    认识容灾备份 构筑一个避风港
    双机热备的实现模式 - 基于共享存储与纯软件方式
    玩大型游戏死机解决方法
    让windows xp开机跳过登陆界面
    在IE7中无法正常访问FTP的解决办法
    STL使用心得
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4437164.html
Copyright © 2020-2023  润新知