LeetCode刷题——复原 IP 地址#93#Medium

复原 IP 地址的思路探讨与源码
     复原 IP 地址的题目如下图,该题属于字符串和回溯类型的题目,主要考察对于回溯遍历方法的使用和字符串本身特性的理解。本文的题目作者想到2种方法,分别是直接多次循环方法和回溯方法,其中回溯方法使用Java进行编写,而直接多次循环方法使用Python进行编写,当然这可能不是最优的解法,还希望各位大佬给出更快的算法。
在这里插入图片描述
    本人认为该题目可以使用回溯方法解决,首先对于字符串的长度进行判断。如果是小于4或者大于12说明本身就不合法,直接排除并返回。然后初始化参数和队列,并且调用回溯搜索函数。在函数内部,我们会判断初始位置和字符串长度是否相等,并且是否尾部的位置是否为0,如果是则直接插入到结果列表里并返回,然后开始循环遍历,因为每个节点可以选择的截取方式只有三种情况,所以这边有三个条件判断,如果初始位置比数组长度要大就直接结束循环,如果尾部的位置乘以3比数组长度减去当前位置的值要小就结束本次循环,如果满足校验函数的结果就将结果加入到列表并继续调用回溯函数,并且将队列的最后一个元素弹出。在校验函数的内部是对IP值本身的范围值和特殊情况值进行校验。最终经过回溯遍历后返回最终结果。那么按照这个思路我们的Java代码如下:

#喷火龙与水箭龟
import java.util.ArrayDeque;
import java.util.ArrayList;
public class Solution {
    public List<String> restoreIpAddresses(String s) {
        int lenNum = s.length();
        List<String> resFinal = new ArrayList<>();
        if (lenNum < 4 || lenNum > 12) {
            return resFinal;
        }
        int step = 4;
        Deque<String> queueList = new ArrayDeque<>(step);
        dfsSearch(s, lenNum, 0, step, queueList, resFinal);
        return resFinal;
    }
    private void dfsSearch(String s, int lenNum, int start, int over, Deque<String> queueList, List<String> resFinal) {
        if (start == lenNum) {
            if (over == 0) {
                resFinal.add(String.join(".", queueList));
            }
            return;
        }
        for (int ir = start; ir < start + 3; ir++) {
            if (ir >= lenNum) {
                break;
            }
            if (over * 3 < lenNum - ir) {
                continue;
            }
            if (examWord(s, start, ir)) {
                String rs = s.substring(start, ir + 1);
                queueList.addLast(rs);

                dfsSearch(s, lenNum, ir + 1, over - 1, queueList, resFinal);
                queueList.removeLast();
            }
        }
    }
    private boolean examWord(String s, int begin, int end) {
        int lenNum = end - begin + 1;
        if (lenNum > 1 && s.charAt(begin) == '0') {
            return false;
        }
        int flag = 0;
        while (begin <= end) {
            flag = flag * 10 + s.charAt(begin) - '0';
            begin = begin + 1;
        }
        return flag >= 0 && flag <= 255;
    }
}

在这里插入图片描述
    显然,我们看到回溯方法的效果还不错,同时还可以使用直接多次遍历搜索的方法进行处理。首先是定义一个函数判断字符串长度是否为1或者2或者3,然后定义参数和初始化列表,并且开始进行三重for循环遍历的操作,如果最里面的循环的下标比字符串长度要大就直接终止循环,否则就调用检验函数进行分段的比较,只有当每一个部分的结果都满足条件,才能将结果插入到列表里,最终返回结果。所以按照这个思路就可以解决,下面是Python代码部分:

#喷火龙与水箭龟
class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        def examWord(word: str) -> bool:
            n = len(word)
            if(n == 1):
                return True
            if(n == 2):
                return int(word[0]) > 0
            if(n == 3):
                if(int(word[0]) > 0):
                    return int(word)<= 255
            return False       
        step = 4
        resFinal = []
        for ir in range(1,step):
            for jr in range(ir+1,ir+step):
                for kr in range(jr+1,jr+step):
                    if(kr >= len(s)):
                        break
                    if examWord(s[:ir]) and examWord(s[ir:jr]) and examWord(s[jr:kr]) and examWord(s[kr:]):
                        resFinal.append(s[:ir] + "." + s[ir:jr] + "." + s[jr:kr] + "." + s[kr:])
        return resFinal

在这里插入图片描述
    从结果来说Java版本的回溯方法的效率还不错,而Python版本的直接多次遍历方法的速度一般,但应该是有更多的方法可以进一步提速的,希望朋友们能够多多指教,非常感谢。

猜你喜欢

转载自blog.csdn.net/qq_26727101/article/details/121577563