问题:到达终点的最小跳跃次数
给定一个整数数组,其中每个元素表示可以从该元素向前进行的最大步数。编写一个函数来返回到达数组末尾的最小跳转次数(从第一个元素开始)。如果元素为0,那么我们就无法遍历该元素。
示例:
输入:arr [] = {1,3,5,8,9,2,6,7,6,8,9} 输出:3(1-> 3 - > 8 - > 9) 第一个元素是1,所以只能到3.第二个元素是3,所以最多可以产生3个步骤,即5个或8个或9个。
来源:http://www.geeksforgeeks.org/minimum-number-of-jumps-to-reach-end-of-a-given-array/
我已经制作了一个线性时间算法来查找到达数组末尾所需的最小跳跃次数。
源代码如下:
int minJumpsUpdated(int arr[], int n)
{
int *jumps = malloc(n * sizeof(int)); // jumps[n-1] will hold the result
int i =1, j = 0;
jumps[0] = 0;
for (i = 1; i < n; ) {
// if i is out of range of arr[j], then increment j
if (arr[j] + j < i && j < i) {
j++;
// else if i is within range of arr[j],
// jumps for ith element would be jumps[j]+1
} else if (arr[j] + j >= i && j < i) {
jumps[i] = jumps[j] + 1;
i++;
} else {
printf("solution does not exist");
return -1;
}
}
printf("jumps: ");
for (i = 0; i < n; i++) {
printf("%d, ", jumps[i]);
}
return jumps[n - 1];
}
示例:
1。)最初i=1, j=0
和arr[] = {1, 3, 6, 1, 0, 9};
jumps[] = 0,0,0,0,0,0
2。)因为i
在arr[j]
范围内,即。 i<= j+arr[j]
,进入第i个位置所需的跳跃次数将是跳到第j个位置的最小跳跃次数+ 1.
i=2, j=0, jumps[] = 0,1,0,0,0,0
3。)i>j+arr[j]
,即j++;
i=2, j=1, jumps[] = 0,1,0,0,0,0
4。)i<=j+arr[j]
,即jumps[i] = jumps[j]+1;
i=3, j=1, jumps[] = 0,1,2,0,0,0
5。)i<=j+arr[j]
,即jumps[i] = jumps[j]+1;
i=4, j=1, jumps[] = 0,1,2,2,0,0
6。)i<=j+arr[j]
,即jumps[i] = jumps[j]+1;
i=5, j=1, jumps[] = 0,1,2,2,2,0
7。)i>j+arr[j]
,即j++;
i=5, j=2, jumps[] = 0,1,2,2,2,0
8。)i<=j+arr[j]
,即jumps[i] = jumps[j]+1;
i=6, j=2, jumps[] = 0,1,2,2,2,3
------结束------
我无法弄清楚该程序在哪个测试用例下无效。我问这个是因为在互联网上优化的解决方案是使用DP,即O(n ^ 2)。我的解决方案是线性时间。即O(n)。所以我假设有一些这种算法无法处理的情况。所以我很好奇它没有处理的情况。
我们将不胜感激。
谢谢。
答案 0 :(得分:5)
算法摘要:
答案 1 :(得分:1)
我认为你的代码只有在有解决方案时才是正确的,如果没有解决方案,如果输入为[0,2,3,4]则该怎么办?
除此之外,我认为你的算法是正确的,当我解决这个问题时,这是我的解决方案,它只需要恒定的空间,并且仍然是线性时间。 基本上对于每个步骤,您只能跳到可以在下一步中跳过大多数步骤的位置。
int jump(int A[], int n) {
int jumps = 0;
if(n < 2){
return jumps;
}
int cur = 0; // current index,
int cur_step;// number of step you can jump in current index
int last; // last index
int temp_max = cur; // temporary max jump distance
int temp_index = cur;// temporary index.
while(cur < n){
last = cur;
cur_step = A[cur];
if((cur + cur_step) >= n-1){ // if reached end of the array, return.
jumps++;
return jumps;
}
for(int ii = cur + 1; ii <= cur + cur_step; ii++){//go thru all the possible next position, and find the one that could jump most steps.
if(A[ii] == 0){
continue;
}
if(A[ii] + ii > temp_max){ // find the one that could jump most steps.
temp_index = ii;
temp_max = A[ii] + ii;
}
}
cur = temp_index; // jump to this position, temp index holds index that jump most steps in next jump.
if(cur != last){
jumps++;
}else{
break;
}
}
return -1;
}
};
答案 2 :(得分:1)
感谢您提出问题并提供代码。它是一个非常简单和下降的方法:)。我使用了相同的方法,并且已经在一个编码平台中通过了所有测试用例。提供下面用java编写的满足所有测试用例的小代码......
public int jump(ArrayList<Integer> a) {
int dp[]=new int[a.size()];
if(a.size()==1 || a.size() == 0)
return 0;
if(a.get(0)==0)
return -1;
Arrays.fill(dp,Integer.MAX_VALUE);
dp[0]=0;
int j=0;
for(int i=1;i<a.size() && j<a.size();)
{
if(j+a.get(j)>=i && dp[j]!=Integer.MAX_VALUE)
{
dp[i]=Math.min(dp[j]+1,dp[i]);
i++;
}
else
j++;
}
if(dp[a.size()-1]==Integer.MAX_VALUE)
return -1;
return dp[a.size()-1];
}