leetcode
leetcode 1051 ~ 1100
顺次数

顺次数

难度:

标签:

题目描述

代码结果

运行时间: 24 ms, 内存: 16.1 MB


/*
 * 题目思路:
 * 1. 使用流处理生成所有可能的顺次数。
 * 2. 利用范围的筛选器过滤掉不在[low, high]范围内的数字。
 */

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SequentialDigitsStream {
    public List<Integer> sequentialDigits(int low, int high) {
        String digits = "123456789";
        int n = digits.length();
        return IntStream.rangeClosed(1, n) // 遍历所有可能的长度
                .boxed() // 转换为Integer
                .flatMap(len -> IntStream.rangeClosed(0, n - len) // 遍历所有可能的起始位置
                        .mapToObj(start -> Integer.parseInt(digits.substring(start, start + len)))) // 生成顺次数
                .filter(num -> num >= low && num <= high) // 过滤范围外的数字
                .sorted() // 排序
                .collect(Collectors.toList()); // 收集结果
    }
}

解释

方法:

这个题解的基本思路是穷举所有可能的顺次数,并检查它们是否落在给定的区间 [low, high] 内。顺次数是由连续递增的数字组成,如 123 或 456。题解首先考虑顺次数可能的长度,从1到9,然后为每个长度生成所有可能的顺次数。这是通过固定顺次数的起始数字,然后逐位构建整数完成的。生成的顺次数如果大于 high,就中断当前长度的进一步探索,避免无效的计算。若顺次数同时大于或等于 low 且小于或等于 high,则将其添加到结果列表中。

时间复杂度:

O(1),因为生成顺次数的总数是有限的。

空间复杂度:

O(1),因为输出列表的大小由有限的顺次数决定。

代码细节讲解

🦆
为什么在生成顺次数时选择从长度1到9进行迭代?顺次数的长度是否有可能超过9?
顺次数是由连续递增的数字组成,因此最长的顺次数是由1到9这9个连续数字构成的。由于数字只有1至9,任何长度超过9的序列都无法满足连续递增的特性,因为这将需要第10个不同的连续数字,而这在1到9的范围内是不存在的。因此,顺次数的最大长度为9,不需要考虑更长的序列。
🦆
在内层循环中,如果顺次数的某一位数字加上起始数字的值超过9,这种情况如何处理?
在算法设计中,通过控制起始数字的选择(`start`),确保生成的每一位数字都不会超过9。起始数字最大可取`9 - length + 1`,这保证了即使在长度最大的情况下,加上起始数字之后的结果也不会超过9。例如,如果长度为3,起始数字最大为7(即7 + 2 = 9),从而避免了任何一位数字超过9的情况。
🦆
当顺次数的构建中途超过high值时,为何可以直接判定为无效而跳出循环?是否有可能后续的数字重新变为有效?
顺次数是由连续增加的数字组成,如果在构建过程中某个顺次数已经超过了high值,则随着数字的进一步增加,它只会变得更大,不可能重新变小回到low到high的区间内。因此,一旦顺次数超过high值,便可以立即判定当前顺次数为无效,并终止进一步的数字添加,以节省不必要的计算资源。
🦆
在检查顺次数是否有效时,为什么要等到构建完整个顺次数后才进行比较,而不是在构建的每个步骤中逐步比较?
在顺次数的构建过程中,只有当整个数字完全构建完成后,才能确定这个数是否落在指定的区间[low, high]内。虽然在构建过程中可以提前终止超过high的无效顺次数,但对于是否低于low的判断只能在顺次数完全形成后进行。此外,顺次数的每一位是连续增加的,我们需要整个顺次数构建完成后才能准确判断其是否符合要求。

相关问题