给定一个非负整数数组,您最初位于数组的第一个索引处。
数组中的每个元素代表该位置的最大跳跃长度。
您的目标是以最小跳跃次数到达最后一个索引。
例如: 给定数组A = [2,3,1,1,4]
到达最后一个索引的最小跳转次数为2.(从索引0跳转1步到1,然后从最后一个索引跳3步。)
我从左到右构建了一个dp []数组,使得dp [i]表示从arr [0]到达arr [i]所需的最小跳跃次数。最后,我们返回dp [n-1]。
我的代码最糟糕的时间复杂度是O(n ^ 2)。
这可以在更好的时间复杂度下完成。
**此问题是从leetcode复制的。
答案 0 :(得分:1)
您可以使用范围最小的段树来解决此问题。段树是一种数据结构,它使您可以维护值的数组,也可以查询该数组的子段的聚合操作。可在此处找到更多信息:https://cses.fi/book/book.pdf(第9.3节)
您将在分区树中存储值d[i]
,如果从索引d[i]
开始,i
是到达最后一个索引所需的最少步骤数。显然,d[n-1] = 0
。一般来说:
d[i] = 1 + min(d[i+1], ..., d[min(n-1, i+a[i])])
,
因此您可以通过向后计算它们来找到d
中的所有值,并在每个步骤之后更新分段树。最终的解决方案是d[0]
。由于对段树的更新和查询都可以在O(log n)中进行,因此整个算法都可以在O(n log n)中进行工作。
答案 1 :(得分:0)
我认为,你可以用这些技术提升计算动力:
你花费O(N)来计算当前的d [i]。但是你可以用d [j]保持一组,
其中j = 0..i - 1.现在你需要使用二进制搜索来找到:
这样的d [j],在所有(0..i-1)中最小,从j位置i-pos是可到达的。
答案 2 :(得分:0)
这是动态编程中的一个简单练习。正如你已经标记过它,我想知道你为什么不试图应用它。
让V[k]
为从k
位置到列表a = (a[0], a[1], ...., a[n-1])
末尾的最小步数。
然后显然是V[n-1]=0
。现在循环向后:
for(int k=n-2;k>=0;--k)
{
int minStep = n + 1;
for(int j=k+1;j<=std::min(n-1,k+a[k]);++j)
{
minStep = std::min(minStep, V[j])
}
V[k]= minStep + 1;
}
循环后,O(a[0]+a[1]+...+a[n-1])
时间V[0]
包含到达列表末尾的最小步数。
为了找到列表中的方法,您可以贪婪地选择操作。也就是说,从位置k
开始,您总是会转到允许的位置l
,其中V[l]
是最小的。
(请注意,我在此处假设列表的正条目,而不是非负的条目。可能很容易从问题中删除可能的零,因为去那里绝对不是最佳的。)
答案 3 :(得分:0)
int jump(vector<int>& a) {
int i,j,k,n,jumps,ladder,stairs;
n = a.size();
if(n==0 || n==1)return 0;
jumps = 1, ladder = stairs = a[0];
for(i = 1; i<n; i++){
if(i + a[i] > ladder)
ladder = i+a[i];
stairs --;
if(stairs + i >= n-1)
return jumps;
if(stairs == 0){
jumps++;
stairs = ladder - i;
}
}
return jumps;
}
答案 4 :(得分:0)
https://leetcode.com/problems/jump-game-ii
class Solution {
public int jump(int[] nums) {
int n = nums.length;
if(n < 2){
return 0;
}
int ans = 1;
int rightBoundaryCovered = nums[0];
for(int i=1;i<n;i++){
if(rightBoundaryCovered >= n-1){
return ans;
}
int currMax = i+ nums[i];
while(rightBoundaryCovered>=i){
currMax = Math.max(currMax, i+nums[i]);
i++;
}
//missed this decrement statement and faced multiple WA's
i--;
ans++;
if(currMax>rightBoundaryCovered){
rightBoundaryCovered = currMax;
}
}
return ans;
}
}
答案 5 :(得分:-1)
Java解决方案(来自编程面试要素):
public boolean canJump(int[] nums) {
int maximumReach = 0;
for(int i = 0; i < nums.length; i++) {
// Return false if you jump more.
if(i > maximumReach) { return false; }
// Logic is we need to keep checking every index the
// farthest we can travel
// Update the maxReach accordingly.
maximumReach = Math.max(i + nums[i], maximumReach);
}
return true;
}