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 在数组跳跃问题中的经典应用,重点考察对时间复杂度的优化能力。
相关推荐
迷枫71213 小时前
达梦 SQL 执行计划操作符与 TRACE、ET 学习笔记
笔记·sql
问心无愧051314 小时前
ctf show web入门106
笔记
星恒随风14 小时前
C++ 类和对象入门(三):拷贝构造、赋值运算符重载和深浅拷贝
开发语言·c++·笔记·学习
小欣加油14 小时前
Leetcode31 下一个排列
数据结构·c++·算法·leetcode·职场和发展
逆光的July14 小时前
Logback 学习笔记
笔记·学习·logback
数智工坊14 小时前
周志华《Machine Learning》学习笔记--第十三章--半监督学习
笔记·学习·机器学习
AOwhisky14 小时前
MySQL 学习笔记(第七期):高可用架构进阶与综合项目实战
linux·运维·笔记·学习·mysql·高可用·mha
_日拱一卒14 小时前
LeetCode:39组合总和
java·算法·leetcode·职场和发展
郝学胜-神的一滴14 小时前
力扣 662 :二叉树最大宽度
java·数据结构·c++·python·算法·leetcode·职场和发展
searchforAI15 小时前
培训视频转文字后怎么做团队复盘?把本地视频整理成AI笔记的实操方案
人工智能·笔记·ai·whisper·音视频·语音识别·腾讯会议