小哆啦的最小跳跃冒险Ⅱ

98 阅读3分钟

小哆啦的最小跳跃冒险

小哆啦开始力扣每日一题的第七天

leetcode.cn/problems/ju…

开始旅程:蛮力初探

小哆啦是一只爱冒险的哆啦A梦,他发现了一片神秘的数字世界。这片世界是一条由整数构成的道路,每个数字代表他在当前位置能跳跃的最大距离。他的任务是找到到达道路尽头的最小跳跃次数。

小哆啦的蛮力方法
“既然每个位置都能跳不同的步数,那我就尝试从每个点出发,探索所有可能的跳跃方式吧!”小哆啦带着这个想法,写下了他的第一版代码:

function jump(nums: number[]): number {
    const n = nums.length;
    let minJumps = Infinity;

    function dfs(index: number, jumps: number): void {
        if (index >= n - 1) {
            minJumps = Math.min(minJumps, jumps);
            return;
        }
        for (let step = 1; step <= nums[index]; step++) {
            dfs(index + step, jumps + 1);
        }
    }

    dfs(0, 0);
    return minJumps;
}

console.log(jump([2, 3, 1, 1, 4])); // 输出:2

这段代码让小哆啦尝试了所有的跳跃路径。但很快,他就发现了问题:“这种方法太慢了!每个位置都要递归地探索所有可能,数字多一点,我的脑袋就要烧坏了!”


优化一:动态规划的智慧

小哆啦想起了自己的时间机器和竹蜻蜓,他决定从未来带回一个优化的想法——动态规划。他对自己说:“如果我已经知道从某个点到终点需要的最少跳跃次数,那么我就可以逆向计算出其他位置的答案!”

他快速实现了第二版代码:

function jump(nums: number[]): number {
    const n = nums.length;
    const dp = Array(n).fill(Infinity);
    dp[0] = 0;

    for (let i = 0; i < n; i++) {
        for (let j = 1; j <= nums[i] && i + j < n; j++) {
            dp[i + j] = Math.min(dp[i + j], dp[i] + 1);
        }
    }

    return dp[n - 1];
}

console.log(jump([2, 3, 1, 1, 4])); // 输出:2

这一次,小哆啦满意地微笑了。“终于快了很多!”他感叹道,“不过,还是有点慢,能不能再快一点呢?”


终极优化:贪心法的点拨

在一次散步中,小哆啦遇见了哆啦小红,她是一个贪心策略的专家。小红告诉他:“如果你总是尽可能跳得更远,那你就可以更快到达终点。没必要每一步都记住所有可能!”

受到启发的小哆啦,迅速优化了代码:

function jump(nums: number[]): number {
    let jumps = 0;
    let currentEnd = 0;
    let farthest = 0;

    for (let i = 0; i < nums.length - 1; i++) {
        farthest = Math.max(farthest, i + nums[i]);

        if (i === currentEnd) {
            jumps++;
            currentEnd = farthest;
        }
    }

    return jumps;
}

console.log(jump([2, 3, 1, 1, 4])); // 输出:2

胜利的终点

小哆啦运行了这段代码,发现它飞快地完成了任务。“哈哈,终于到达了终点!而且是用最少的跳跃次数!”

他总结道:“从尝试所有可能,到使用动态规划的智慧,再到贪心策略的点拨,我终于掌握了这片数字世界的规则。这次冒险真是太棒了!”

小哆啦带着满满的成就感,继续踏上了下一个未知的旅程……