问题:到达终点的最小跳跃次数
给定一个整数数组,其中每个元素表示可以从该元素向前执行的最大步数。编写一个函数返回到达数组末尾的最小跳转次数(从第一个元素开始)。如果一个元素是0,那么我们不能移动该元素。
例子:
输入:arr[]={1,3,5,8,9,2,6,7,6,8,9}输出:3(1-
来源: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]
ie.i的范围内
i=2, j=0, jumps[] = 0,1,0,0,0,0
3.
i
i=2, j=1, jumps[] = 0,1,0,0,0,0
4.
i
i=3, j=1, jumps[] = 0,1,2,0,0,0
5.)<代码>i
i=4, j=1, jumps[] = 0,1,2,2,0,0
6.
i
i=5, j=1, jumps[] = 0,1,2,2,2,0
7.)<代码>i
i=5, j=2, jumps[] = 0,1,2,2,2,0
8.
i
i=6, j=2, jumps[] = 0,1,2,2,2,3
------ 结束 ------
我无法确定该程序在哪个测试用例下不能工作。我这样问是因为在互联网上,优化的解决方案是使用DP,即O(n^2)。我的解决方案是线性时间。i、 e.O(n)。因此,我假设有一些情况,这种算法将无法处理。因此,我很好奇它不处理什么情况。
谢谢你的帮助。
非常感谢。
感谢您提出问题并提供代码。这是一种非常简单的方法:)。我使用了相同的方法,它通过了其中一个编码平台中的所有测试用例。提供以下用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];
}
我认为您的代码只有在有解决方案的情况下才是正确的,如果没有解决方案怎么办?例如,如果输入是[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;
}
};
您的算法摘要:
i
,直到arr[j]j
首先:
是的,它在O(n)
中运行,因为在最坏的情况下,算法只将i
和j
从1
推送到n
一次。
第二,
我没有看到一个证据证明O(n²)
是最佳时间复杂度。
修复无解决方案的情况
确保j
问题声明:给定数组:[1,0,1,0,1,1,1,1,1,0,1,1,1,0]输出:到达结束所需的最小步骤 条件: 0上的步骤是退出 我已经完成了不使用DP的情况下的使用,是否存在针对此问题的DP解决方案。 我的代码:
我处理下面提供的一个可编码性问题, 斐波那契序列使用以下递归公式定义: 一只小青蛙想去河的对岸。青蛙最初位于河的一边(位置−1),想要到达另一边(位置N)。青蛙可以跳过任何距离F(K),其中F(K)是第K个斐波那契数。幸运的是,河上有许多树叶,青蛙可以在树叶之间跳跃,但只能在N号位置的岸边方向跳跃。 河上的叶子用一个由N个整数组成的数组表示。数组A的连续元素表示从0到N的连续位置− 1在河上。阵列
问题是获取和数组中相应的索引,这些索引导致以较小的跳跃结束。例如:将需要s... 我说的跳跃是指跳跃;i、 e需要多少啤酒花。如果您是一个特定的索引,则可以通过该索引中的值进行跳跃。 下面是我在中的实现,它正确地给出了最小的跳转次数,但是我很难用
给定一个整数数组,其中每个元素表示可以从该元素向前执行的最大步数。编写一个函数,返回到达数组末尾(从第一个元素开始)的最小跳转次数。如果元素为0,则无法在该元素中移动。 输入: arr[] = { 1, 3, 5, 8, 9, 2, 6, 7, 6, 8, 9} 输出: 3(1- 发现了从动态规划方法到其他线性方法的多种方法。我无法理解所谓的时间线性方法。这里是一个链接,其中提出了一种线性方法。
给定一个数组,从第一个元素开始验证到达终点需要多少步。 示例:arr=[1,3,5,8,4,2,6,7,0,7,9] 1- 3个步骤。 到目前为止,我从极客那里得到了以下代码: 但是我想打印出哪些数字是最短的路径(1-3-8)。我如何调整代码来做到这一点? 我试图创建一个j的列表,但是由于5在循环中进行了测试,所以也添加了它。 问题的链接:https://www.geeksforgeeks.org
下面是寻找最小跳跃次数的算法谜题。发布了详细的问题声明和两个代码版本来解决这个问题。我做了测试,似乎两个版本都可以工作,我的第二个版本是版本一代码的优化版本,这使得我从开始,而不是持续增加,这可以通过不迭代所有的插槽来节省时间数组。 我的问题是,想知道我的第二个版本代码是否100%正确?如果有人发现任何逻辑问题,请指出。 问题陈述 给定一个非负整数数组,您最初位于数组的第一个索引处。 数组中的每个