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 在数组跳跃问题中的经典应用,重点考察对时间复杂度的优化能力。
相关推荐
小李不想当小白19 分钟前
DMA直接存储器存取(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·分享
午彦琳2 小时前
2026.9.17
数据结构·算法·leetcode
木井巳2 小时前
【记忆化搜索】不同路径
java·算法·leetcode·深度优先·剪枝·推荐算法
2601_965384262 小时前
口腔黏膜清洁的工程化路径:从表面形貌表征到清洁策略匹配
经验分享·笔记
泡泡鱼(敲代码中)2 小时前
Python 容器类型学习笔记:列表、元组、字典、集合
开发语言·笔记·python·pycharm
Hotchip_MEMS4 小时前
传统咪头与MEMS硅麦:雾化器气流传感方案对比
人工智能·笔记·物联网·电脑·制造
志尊宝4 小时前
Vue3 零基础每日笔记(040):Vite 创建 Vue3 + TS 项目——企业标配从这一篇开始
笔记·vue·html·前端开发·软件开发
水云桐程序员4 小时前
量子力学概论,量子力学概念总结
笔记·科技·学习·量子计算
darin_ฅ( ̳• ◡ • ̳)ฅ15 小时前
【 Obsidian】2026版-Obsidian安装Automatic Table of Contents 插件一键生成文章目录
笔记
2401_850122045 小时前
航空、轨交、汽车线束防护有什么不同?三大行业的共性、差异与选型逻辑
经验分享·笔记·科技