leetcode
leetcode 2101 ~ 2150
最长上传前缀

最长上传前缀

难度:

标签:

题目描述

代码结果

运行时间: 300 ms, 内存: 65.3 MB


/*
 * 题目思路:
 * 1. 使用一个布尔数组来记录每个视频是否被上传。
 * 2. 使用一个变量来记录当前最长的上传前缀。
 * 3. 在上传视频时,标记相应的视频为已上传,并更新最长的上传前缀。
 * 4. 在调用 longest 方法时,返回当前的最长上传前缀。
 * 5. 使用 Java Stream 来处理数组。
 */

import java.util.stream.IntStream;

class LUPrefix {
    private boolean[] uploaded;
    private int longestPrefix;

    public LUPrefix(int n) {
        uploaded = new boolean[n + 1]; // 初始化上传数组
        longestPrefix = 0; // 初始化最长前缀
    }

    public void upload(int video) {
        uploaded[video] = true; // 标记视频已上传
        // 使用 IntStream 更新最长上传前缀
        longestPrefix = IntStream.range(longestPrefix + 1, uploaded.length)
                                  .filter(i -> uploaded[i])
                                  .reduce((first, second) -> second)
                                  .orElse(longestPrefix);
    }

    public int longest() {
        return longestPrefix; // 返回最长上传前缀
    }
}

解释

方法:

此题解主要使用一个数组 `calcu` 来跟踪哪些视频已上传,其中数组的索引对应视频编号减一(因为视频编号从1开始,数组索引从0开始)。当上传视频时,对应的数组位置被设置为1。为了高效跟踪最长上传前缀,使用了一个额外的变量 `count` 来记录当前最长上传前缀的长度。每次 `upload` 操作后,从 `count` 开始检查,如果连续的视频都已上传,则 `count` 增加,反之停止。这样,`longest` 方法只需返回 `count` 的值即可。

时间复杂度:

O(n) 平摊时间复杂度,其中 n 是操作总数

空间复杂度:

O(n)

代码细节讲解

🦆
算法中使用了`while`循环来更新`count`值,如果连续多次调用`upload`方法而不调用`longest`方法,`count`的更新是否会导致性能下降?
在每次调用`upload`方法时更新`count`并不会显著影响性能,因为`count`的更新直接依赖于上传的视频是否连续。尽管`while`循环可能在某些情况下执行多次(例如连续上传多个视频),但每个视频编号最多只被检查一次。因此,整体性能影响是线性的,与视频总数成正比。此外,这种方法可以避免在每次调用`longest`时进行重复的、可能更耗时的计算。
🦆
在`upload`方法中,为什么选择在视频上传后立即更新`count`,而不是在调用`longest`方法时统一计算?
选择在每次`upload`后立即更新`count`是为了优化`longest`方法的效率,使其能够在O(1)时间复杂度内返回结果。如果延迟更新直到调用`longest`,那么每次调用`longest`都可能需要遍历整个`calcu`数组来计算最长上传前缀,特别是在高频调用的场景下这将非常低效。立即更新保证了数据的即时性和准确性,同时使得`longest`方法的调用非常高效。
🦆
如果在实际应用中,上传序列并不是连续的,例如上传了1, 2, 4, 5,但没有上传3,这种情况下算法的表现如何?
在这种非连续上传的场景下,算法依然能够正确处理并返回当前最长的连续上传前缀。例如在上传了1, 2, 4, 5的情况下,由于3号视频未上传,`count`会停留在2,这意味着最长连续上传前缀的长度是2。算法设计确保只有当一个序列完全连续时,`count`才会增加,确保了其准确性和鲁棒性。

相关问题