【发布时间】:2020-06-12 20:39:23
【问题描述】:
我正在练习 leet 代码问题,并希望更全面地了解如何确定大 O 表示法。我对以下问题的解决方案的算法复杂度是多少?
O(n^2) ? 对于 n 中的每个项目,我可以再循环 n[i] 次。还是 O(n) ?
给定一个非负整数数组,您最初位于数组的第一个索引处。
数组中的每个元素代表您在该位置的最大跳跃长度。
确定您是否能够到达最后一个索引。
输入:[2,3,1,1,4]
输出:真
解释:从索引 0 跳 1 步到 1,然后跳 3 步到最后一个索引。
var canJump = function(nums) {
let validIndices = {};
for(let i = nums.length - 1; i >= 0; i--) {
let currentNum = nums[i];
if(currentNum + i >= nums.length - 1) {
validIndices[i] = true;
} else {
while(currentNum > 0) {
if(validIndices[i + currentNum]) {
validIndices[i] = true;
}
currentNum--;
}
}
}
return !!validIndices[0];
};
【问题讨论】:
-
O(n²) 听起来不对,因为 n[i] 与 n 不同。但是,在这种情况下,最大跳跃长度至少以 n 为界(跳得超过步数没有意义),因此它至少不会超过 O(n²)。
-
是的,当数组像 [n, n-1, n-2, ..., 3, 2, 1, 0] 时,最坏的情况是 O(n^2)。如果你已经设置了
validIndices[i] = true;,那么如果你有一个来自内部循环的break,在平均情况下会更快,但在最坏的情况下仍然是 O(n^2)。 -
话虽如此,除非我遗漏了什么,否则问题可能可以在 O(n) 内解决。只需反向扫描数组,注意是否有一段 0(您必须跳过的单元格),以及在那些大到足以弥合差距的前面是否有一个 n[i]。
-
感谢 cmets。 @tobias_k 位置 n[i] 的值是从该位置允许的最大跳跃次数。我最初认为我可以检查 n[i] 是否足够大以弥合差距,但您仍然需要考虑从该位置的最大跳跃到最小跳跃的跳跃。因此,除非我误解了您的意思,否则我认为您提出的解决方案不会起作用-这很有可能!这是我的第一次尝试 - 它有效,但速度很慢。
标签: algorithm