LeetCode 每日一题笔记 日期:2026.05.18 题目:1345. 跳跃游戏 IV

LeetCode 每日一题笔记

0. 前言

  • 日期:2026.05.18
  • 题目:1345. 跳跃游戏 IV
  • 难度:困难
  • 标签:数组、广度优先搜索、哈希表

1. 题目理解

问题描述

给定一个整数数组 arr,你从下标 0 开始。每一步可以从下标 i 跳到:

  1. i + 1(需满足 i + 1 < arr.length
  2. i - 1(需满足 i - 1 >= 0
  3. 任意 j(需满足 arr[j] == arr[i]j != i

求到达数组最后一个下标的最少操作次数

示例

输入:arr = [100,-23,-23,404,100,23,23,23,3,404]

输出:3

解释:最优路径:0 → 4 → 3 → 9,共3次跳跃。
输入:arr = [7]

输出:0

解释:初始位置就是终点,无需跳跃。

2. 解题思路

核心观察

  • 这是典型的无权图最短路径问题,BFS是天然的最优解法;
  • 同值跳跃会产生大量边,若不优化会导致超时;
  • 关键优化:处理完一个值的所有下标后,立即从哈希表移除该值,避免重复处理。

算法步骤

  1. 预处理哈希表:建立「值 → 对应下标列表」的映射;
  2. BFS初始化:队列加入起点 0,标记已访问;
  3. 逐层遍历队列,每层对应一步操作;
  4. 对当前节点,依次处理:
    • 右邻居 i+1
    • 左邻居 i-1
    • 所有同值下标
  5. 处理完同值下标后,从哈希表移除该值;
  6. 到达终点时立即返回当前步数。

3. 代码实现

java 复制代码
package lc1345;

import java.util.*;

class Solution {

    int bfs(HashMap<Integer, List<Integer>> map, int[] arr) {
        int res = 0;
        int last = arr.length - 1;
        boolean[] visited = new boolean[arr.length];
        Queue<Integer> queue = new LinkedList();
        queue.offer(0);
        while (!queue.isEmpty()) {
            int m = queue.size();
            for (int i = 0; i < m; i++) {
                int n = queue.poll();
                visited[n] = true;
                if (n == last) {
                    return res;
                }
                if (n < last && !visited[n + 1]) {
                    visited[n + 1] = true;
                    queue.offer(n + 1);
                }
                if (n > 0 && !visited[n - 1]) {
                    visited[n - 1] = true;
                    queue.offer(n - 1);
                }
                if (map.containsKey(arr[n])) {
                    List<Integer> list = map.get(arr[n]);
                    for (int num : list) {
                        if (num != n && !visited[num]) {
                            visited[num] = true;
                            queue.offer(num);
                        }
                    }
                    map.remove(arr[n]);
                }
            }
            res += 1;
        }
        return -1;
    }

    public int minJumps(int[] arr) {
        HashMap<Integer, List<Integer>> map = new HashMap<>();
        for (int i = arr.length - 1; i >= 0; i--) {
            map.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i);
        }
        return bfs(map, arr);
    }
}

4. 代码优化说明

减少if分支判断,合并重复逻辑,使用更高效的队列实现:

java 复制代码
package lc1345;

import java.util.*;

class Solution {
    public int minJumps(int[] arr) {
        int n = arr.length;
        if (n == 1) return 0;
        
        HashMap<Integer, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            map.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i);
        }
        
        boolean[] visited = new boolean[n];
        Queue<Integer> queue = new ArrayDeque<>();
        queue.offer(0);
        visited[0] = true;
        int step = 0;
        
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                int curr = queue.poll();
                if (curr == n - 1) return step;
                
                // 处理左右邻居
                if (curr + 1 < n && !visited[curr + 1]) {
                    visited[curr + 1] = true;
                    queue.offer(curr + 1);
                }
                if (curr - 1 >= 0 && !visited[curr - 1]) {
                    visited[curr - 1] = true;
                    queue.offer(curr - 1);
                }
                
                // 处理同值下标
                if (map.containsKey(arr[curr])) {
                    for (int next : map.get(arr[curr])) {
                        if (!visited[next]) {
                            visited[next] = true;
                            queue.offer(next);
                        }
                    }
                    map.remove(arr[curr]);
                }
            }
            step++;
        }
        return -1;
    }
}

5. 复杂度分析

  • 时间复杂度 :O(n)O(n)O(n)

    • 每个下标最多入队一次,每个值最多处理一次;
    • 哈希表移除操作避免了重复处理同值下标,是不超时的关键。
  • 空间复杂度 :O(n)O(n)O(n)

    • 哈希表、队列、访问数组的空间开销均为线性级。

6. 总结

  • 核心思路:BFS 求最短路径 + 哈希表批量处理同值跳跃
  • 关键优化:处理完一个值的所有下标后立即从哈希表移除,避免重复入队;
  • 本题是 BFS 在数组跳跃问题中的经典应用,重点考察对时间复杂度的优化能力。
相关推荐
殷忆枫1 小时前
AI笔记三十七:AI边缘端道桥安全监测系统:YOLOv8n推理与Web监控全解析
笔记·yolo
hold?fish:palm2 小时前
9 找到字符串中所有字母异位词
c++·算法·leetcode
逸模2 小时前
轻加盟模式,稳住品牌统一调性的思路
笔记·建模·公装·翻模·交底
Sw1zzle2 小时前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木2 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
whyTeaFo3 小时前
GAMES101: Lecture 10: Geometry 1 (Introduction) ppt笔记
笔记
啦啦啦啦啦zzzz3 小时前
算法:回溯算法
c++·算法·leetcode
sulikey3 小时前
个人Linux操作系统学习笔记11 - 环境变量
linux·笔记·学习
德迅云安全-上官4 小时前
德迅云安全游戏盾与DDoS高防IP对比:差异、优势及选型指南
tcp/ip·游戏·ddos
依然范特东4 小时前
强化学习笔记2--bellman equation
人工智能·笔记