【华为2018年校园招聘】软件开发---跳跃比赛

题目描述
给出一组正整数,你从第一个数向最后一个数方向跳跃,每次至少跳跃1格,每个数的值表示你从这个位置可以跳跃的最大长度。计算如何以最少的跳跃次数跳到最后一个数。

输入描述:
第一行表示有多少个数n
第二行开始依次是1到n个数,一个数一行

输出描述:
输出一行,表示最少跳跃的次数。

示例1
输入
7
2
3
2
1
2
1
5
输出
3

说明
7表示接下来要输入7个正整数,从2开始。数字本身代表可以跳跃的最大步长,此时有2种跳法,为2-2-2-5和2-3-2-5都为3步

解题思路:如何选择步长是关键。
我的解题思路过程如下:
(1)把最后一个数当作终点,从最后一个数开始,往前找,找到一个可以一步到达终点且距离终点最远的那个数;
(2)把刚刚找到的数,作为终点,重复(1)的步骤
(3)到达起点的数时,就终止。

怎么理解“可以一步到达终点且距离终点最远”呢?
这里写图片描述
如上图,肯定选择2,而不是1.

实际上就是保证每一步跨越尽可能大的距离,那么需要走的步数肯定就是最小的。

思路是对的,但是在代码实现的时候出现问题了,如何保证你找到的那个位置的数就是“可以一步到达终点且距离终点最远”呢?这样就必须一直遍历到起点才能知道,这就存在很大的时间消耗了。

既然是距离终点最远,那么反过来,就是距离起点最近,
所以解题思路换成如下:
(1)从起点开始,找到第一个可以一步到达终点的位置;
(2)把刚刚找到的位置作为新的终点,重复(1);
(3)直到新的终点和起点重合,结束。

思路出来了,代码就很简单了,就是个简单的递归,而且时间消耗也不会很大,因为每次递归时只需要找到第一个可以一步到达终点的位置即可。

附上源码:

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] num = new int[n];
        for (int i = 0; i < n; i++)
            num[i] = sc.nextInt();
        sc.close();
        System.out.println(jump(n - 1, num));
    }
    public static int jump(int end, int[] num) {
        if (end == 0)
            return 0;
        int i = 0;
        while (num[i] < (end - i))
            i++;
        return 1+jump(i, num);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_16403141/article/details/79887084