zoukankan      html  css  js  c++  java
  • [LeetCode#93]Restore IP Addresses

    The problem:

    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)

    My analysis:

    his problem is not complex, but it includes many important skills in implementing a recursion algorithm.
    Key: this problem is a finite recursion problem. (we could clearly say the recursion only and must have four layers)
    seg4. seg3. seg2. seg1
    What's more, we could use extra required properity of a valid IP address to limit searching branches.
    1. each segement could only hold at most 3 characters and at least 1 character.

    int len;
    if (s.length() < start + 3) //in case of the last segment may not be able to have 3 characters left to search. 
        len = s.length();
    else 
        len = start + 3; 
    
    for (int i = start; i < len; i++) {...}

    2. a segement must only hold the number in the range [0, 255]:  0<= segment_number <=255.

    if (cur_temp <= 255 && cur_str.length() <= 3) {
        ans += cur_str;
        ret.add(ans);
    }

    3. if a segement's initial character is '0', and the segement's length is larger than 1 (e. "00", "011"). this case is illegal, we should stop searching along this branch. 

    if (cur_str.length() > 1 && cur_str.charAt(0) == '0')
        return; 

    4. if the left characters's length is smaller than the segment's number. (e. "11", seg3. seg2. seg1)
    in this case, it's impossible to assgin enough character for each segment.
    5. if the left characters's length is larger than three times of the segment's number. (e. "1111101", seg2, seg1)

    if (digit_index * 3 < s.length() - 1 - start + 1) 
        return; 
    if (digit_index > s.length() - 1 - start + 1)
        return; 

    Important skills:
    1. How to preserve the searching answers ?
    1.1 we usually use an ArrayList and pass it around all recursion.
    1.2 we add the answer at the final recursion level(in this problem is segment1).if the searching branch can reach segement4,
    it means the branch is valid in segement 1, segement2 and segment3(otherwise, we have already stop the searching along this branch).

    if (digit_index == 1) { //only the last section left, we should check it. 
        cur_str = s.substring(start, s.length());
        cur_temp = Integer.parseInt(cur_str);
                
        if (cur_str.length() > 1 && cur_str.charAt(0) == '0')
            return; 
                    
        if (cur_temp <= 255 && cur_str.length() <= 3) {
            ans += cur_str;
            ret.add(ans);
        }
        return;
    }

    2. How to stop the searching on the invalid branches? (very imprtant)
    Note: In a recursion level, we may extend to several sub searching branches.

    for (int i = start; i < len; i++) {...}

    2.1 if the invalid condition would invalid all sub searching branches, we use "return" directly. 

    if (digit_index * 3 < s.length() - 1 - start + 1) //if the left elements' number exceeds the left digits
            return; 

    2.2 (note) if the invalid condition would only invalid one sub search branches, we should use "continue" to skip this search    branch.(since it can never reach the next level recursion)  

     for (int i = start; i < len; i++) { //only three numbers possible for this section
            cur_str = s.substring(start, i + 1);
            cur_temp = Integer.parseInt(cur_str);
            String ans_temp = new String(ans); //this is very very important!!!, must be a sperate new string!
            
            if (cur_str.length() > 1 && cur_str.charAt(0) == '0')
                continue;

    3. Use the new object properly. (very important).
    3.1 Since the Java pass all things by value, the mainpulating string would be different at different rucursion level.

    private void helper(String s, int start, int digit_index, String ans, ArrayList<String> ret) {
        ....
        helper(s, i + 1, digit_index - 1, ans, ret);
        ....
    }

    Even with the same name "ret", the manipulating object at present recursion level and next recursion level would be different Strings. Therefore, the manipulation would not interfere with each other. 

    3.2 However, we should be very careful when there are several sub-searching branches in the same recursion level. In this case, it's very likely to use the same object repeatedly, which would in a very strange and wrong output.
    Wrong way:

    for (int i = start; i < len; i++) { //only three numbers possible for this section
            
        cur_str = s.substring(start, i + 1);
        cur_temp = Integer.parseInt(cur_str);
                
        if (cur_str.length() > 1 && cur_str.charAt(0) == '0')
            continue; 
                    
        if (cur_temp > 255) //the three digits is not valid
            return;
                
        ans += cur_str;
        helper(s, i + 1, digit_index - 1, ans, ret);
    }

    Note: the same ans was reused wen i = start to len.
    Improved Solution: we new a string for each sub-search branches.

    for (int i = start; i < len; i++) { 
            
        cur_str = s.substring(start, i + 1);
        cur_temp = Integer.parseInt(cur_str);
        String ans_temp = new String(ans); //this is very very important!!!, must be a sperate new string!
                
        if (cur_str.length() > 1 && cur_str.charAt(0) == '0')
            continue; 
                    
        if (cur_temp > 255) //the three digits is not valid
            return;
                
        ans_temp += cur_str;
        helper(s, i + 1, digit_index - 1, ans_temp, ret);
    }

    My first ugly solution:

    public class Solution {
        public List<String> restoreIpAddresses(String s) {
            
            ArrayList<String> ret = new ArrayList<String> ();
            if (s == null||s.length() < 4||s.length() > 12)
                return ret;
            
            helper(s, 0, 4, "", ret);
            return ret; 
        }
        
        private void helper(String s, int start, int digit_index, String ans, ArrayList<String> ret) {
    
            int cur_temp; 
            String cur_str;
            
            if (digit_index * 3 < s.length() - 1 - start + 1) //if the left elements' number exceeds the left digits
                return; 
                
            if (digit_index > s.length() - 1 - start + 1)
                return; 
                
            if (digit_index != 4) //if not the first section, we appen a '.' first! 
                ans +=".";
            
            if (digit_index == 1) { //only the last section left, we should check it. 
                
                cur_str = s.substring(start, s.length());
                cur_temp = Integer.parseInt(cur_str);
                
                if (cur_str.length() > 1 && cur_str.charAt(0) == '0')
                    return; 
                    
                if (cur_temp <= 255 && cur_str.length() <= 3) {
                    ans += cur_str;
                    ret.add(ans);
                }
                
                return;
            }
            
            int len;
            if (s.length() < start + 3)
                len = s.length();
            else 
                len = start + 3; 
            
            
            for (int i = start; i < len; i++) { //only three numbers possible for this section
            
                cur_str = s.substring(start, i + 1);
                cur_temp = Integer.parseInt(cur_str);
                String ans_temp = new String(ans); //this is very very important!!!, must be a sperate new string!
                
                if (cur_str.length() > 1 && cur_str.charAt(0) == '0')
                    continue; 
                    
                if (cur_temp > 255) //the three digits is not valid
                    return;
                
                ans_temp += cur_str;
                helper(s, i + 1, digit_index - 1, ans_temp, ret);
            }
        }
    }

    A more elegant solution:

    public class Solution {
        public List<String> restoreIpAddresses(String s) {
            
            ArrayList<String> ret = new ArrayList<String> ();
            if (s == null||s.length() < 4||s.length() > 12)
                return ret;
            
            helper(s, 0, 4, "", ret);
            return ret; 
        }
        
        private void helper(String s, int start, int digit_index, String ans, ArrayList<String> ret) {
            
            String seg_str;
            
            if (s == null || s.length() == 0)
                return;
            
            if (s.length() - start > 3 * digit_index) //the number of characters left = s.length() - 1 - start + 1
                return;
            
            if (s.length() - start < digit_index)
                return;
            
            
            if (digit_index == 1) {
                seg_str = s.substring(start);
                if (isvalid(seg_str) == true) { //record or stop
                    ret.add(ans + "." + seg_str);
                }
                return;
            }
            
            int len; 
            if (s.length() >= start + 3) //not exceed the left string's length
                len = start + 3;
            else 
                len = s.length();
            
            for (int i = start + 1; i <= len; i++) {
                seg_str = s.substring(start, i);//i is the exclusive boundary. 
                if (isvalid(seg_str) == false)
                    continue;
                
                /*pass the validation*/
                if (digit_index == 4) {
                    helper(s, i, digit_index - 1, ans + seg_str, ret);  //make no changes to ans at all!!!
                } else {
                    helper(s, i, digit_index - 1, ans + "." + seg_str, ret);
                }
            }
        }
        
        private boolean isvalid (String s) { //to devise a proper function!!!
            
            if (s.length() == 0 || s.length() > 3)
                return false;
            
            int temp_int = Integer.parseInt(s);
            if (temp_int < 0 || temp_int > 255)
                return false;
            
            if (s.length() > 1 && s.charAt(0) == '0')
                return false;
            
            return true;
        }
    }
  • 相关阅读:
    svn不提交.net项目中的bin
    java 与C# 时间格式 交互
    生成菜单序列号
    ashx 方法模板
    webservice使用方法
    如何配置IIS服务器?
    zepto.fullpage
    模拟单选框
    star score
    Hover show tips
  • 原文地址:https://www.cnblogs.com/airwindow/p/4214391.html
Copyright © 2011-2022 走看看