leetcode
leetcode 2901 ~ 2950
复原 IP 地址

复原 IP 地址

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 22 ms, 内存: 16.0 MB


/*
 * 思路:
 * 1. 使用stream流处理和组合字符串的所有可能分割。
 * 2. 过滤掉无效的IP部分和长度不合适的组合。
 */
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SolutionStream {
    public List<String> restoreIpAddresses(String s) {
        return IntStream.rangeClosed(1, 3).boxed()
            .flatMap(i -> IntStream.rangeClosed(1, 3).boxed()
                .flatMap(j -> IntStream.rangeClosed(1, 3).boxed()
                    .flatMap(k -> IntStream.rangeClosed(1, 3).boxed()
                        .map(l -> new int[]{i, j, k, l}))))
            .filter(parts -> parts[0] + parts[1] + parts[2] + parts[3] == s.length())
            .map(parts -> new String[]{
                s.substring(0, parts[0]),
                s.substring(parts[0], parts[0] + parts[1]),
                s.substring(parts[0] + parts[1], parts[0] + parts[1] + parts[2]),
                s.substring(parts[0] + parts[1] + parts[2])
            })
            .filter(parts -> isValid(parts))
            .map(parts -> String.join(".", parts))
            .collect(Collectors.toList());
    }

    private boolean isValid(String[] parts) {
        for (String part : parts) {
            if (part.length() > 1 && part.startsWith("0")) return false;
            int value = Integer.parseInt(part);
            if (value < 0 || value > 255) return false;
        }
        return true;
    }
}

解释

方法:

本题解使用了递归回溯的方法来构建所有可能的有效IP地址。从字符串的开始位置出发,通过递归地尝试每一个可能的分段(最长为3个字符),并且每段数字必须在0到255之间。特别地,单个'0'可以作为一段,但是'0'不能作为其他数字的前缀。在每一步递归中,如果当前的部分字符串符合IP地址的一个段的要求,就将其加到当前正在构建的IP地址中。当字符串被完全使用并且构建的IP地址由四段组成时,这个地址就被认为是一个有效的IP地址。通过这种方式,递归函数遍历所有可能的分段方式,直到找到所有的有效IP地址。

时间复杂度:

O(1)

空间复杂度:

O(n)

代码细节讲解

🦆
在递归回溯算法中,为什么选择使用字符串拼接来构建IP地址片段而不是使用数组或其他数据结构?
在递归回溯算法中使用字符串拼接来构建IP地址片段主要是因为字符串拼接简单直观且易于操作。使用字符串可以直接通过添加'.'来分隔IP地址中的各个部分,这样的操作直接反映了IP地址的结构。此外,字符串拼接使得在递归的每一层中传递和修改地址片段变得更加方便。如果使用数组或其他数据结构,虽然可以提供更灵活的数据操作,但在每次递归调用中需要更多的操作来管理和转换数据格式,比如在递归结束后还需要将数组转换为字符串格式以符合IP地址的标准显示格式。因此,考虑到实现的简洁性和直观性,字符串拼接是一种有效的选择。
🦆
在处理以'0'开头的段时,为什么可以直接将'0'作为一个完整的段而不考虑后面的数字?
在IP地址中,'0'可以单独作为一个段,但是不能作为其他数字的前缀。这是因为在IP地址的表示中,前导零是不允许的,例如'01'或'001'是不合法的。因此,如果一个段以'0'开头,它必须单独作为一个段,后面的数字不能包含在这个段内,否则会导致误解或不被接受的IP格式。这种处理方式符合IP地址的标准规定,确保了生成的IP地址的有效性。
🦆
函数中递归的退出条件是基于已构建的IP地址段数多于4,这种设计是否能有效地减少不必要的递归调用?
是的,这种设计能有效地减少不必要的递归调用。IP地址由四个数字段组成,每个字段由1到3个数字构成。如果在递归过程中已经构建了超过四个段,那么继续递归不仅没有意义,而且会导致生成无效的IP地址。通过设置递归退出条件为段数超过四个,可以及时终止那些不可能生成有效IP地址的路径,从而提高算法的效率和性能。这种策略是减少计算量和避免无效计算的有效方法。

相关问题