1345. 跳跃游戏 IV

题目链接

如果没有从i跳到j,则根据i可以跳掉i+1,或者i-1,能够利用

但是现在有3种方式,可以从当前位置跳到i+1, i-1, j(arri = arrj),我可以理解为一种搜索的方式吗,在每一步搜索过程中统计当从下标0跳到数组最后一个元素的时候,维护最少跳动次数。

例如数组arr = [100, -23, -23, 404, 100, 23, 23, 23, 3, 404],一共最少需要3次跳动,从下标0到4到3到9。

我们可以理解为一个图,目的是求图的最短路,可以用BFS来解决。

首先将数组中每个下标视为节点,边的构建则是按照题意得三种操作方式,

  • i -> i + 1
  • i -> i - 1
  • i -> j (arri = arrj)

然后求节点0到节点n-1的最短路径。使用BFS可以天然保证第一次到达终点时,经过的层数最少。之所以不用DFS是因为DFS找到的是一条路径,需要遍历所有可能才能比较最小值,效率低。

BFS是按层扩展,第一次抵达终点时就是最少跳数,不需要继续搜索。

步骤:

  • 维护一个队列用于BFS搜索,存入下标0的元素
  • 为了方便找到相同元素值得下标,通过Map维护
  • 使用dist数组维护最短距离,disti 存储从起点 0 到下标 i 的最少跳数。BFS 按层扩展的特性保证,第一次给某个节点赋值时,它就已经是最短距离了,不需要后续更新。
    • 同时dist还充当了已访问标记,if (dist[nb] == -1)表示还没访问过,所以初始化dist为-1。一旦某个节点被加入队列,立刻赋值 distnb = nextDist,后续再遇到这个节点时条件不成立,自然跳过。
  • 同时确保每个节点最多入队一次,
java 复制代码
class Solution {
    public int minJumps(int[] arr) {
        // 处理边界
        int n = arr.length;
        if (n == 1) return 0; 

        // 建立相同元素值的Map下标
        Map<Integer, List<Integer>> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            // // 如果不存在键则创建
            // if (!map.containsKey(arr[i])) {
            //     map.put(arr[i], new ArrayList<>());

            // }
            // // 存在直接存入
            // map.get(arr[i]).add(i);

            map.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i);
        }
        // 统计距离数组
        int[] dist = new int[n];
        // 初始化
        Arrays.fill(dist, -1);
        // 从下标0开始出发,
        dist[0] = 0;
        // 定义队列
        Queue<Integer> queue = new ArrayDeque<>();
        // 放入下标0
        queue.offer(0);

        // BFS遍历
        while (!queue.isEmpty()) {
            // 获取队头元素
            int cur = queue.poll();
            int nextDist = dist[cur] + 1; // 即下一个更新的操作部署
            // 三类邻居
            List<Integer> neighbors = new ArrayList<>();
            // 判断左右位置是否合适
            if (cur - 1 >= 0) neighbors.add(cur - 1);
            if (cur + 1 < n) neighbors.add(cur + 1);
            // 找到相同元素值得下标
            if (map.containsKey(arr[cur])) {
                neighbors.addAll(map.get(arr[cur]));
                // 关键优化:防止重复处理同值节点
                map.remove(arr[cur]);
            }

            // 处理邻居
            for (int nb : neighbors) {
                if (dist[nb] == -1) {
                    // 没有被访问过
                    dist[nb] = nextDist;
                    if (nb == n - 1) return nextDist; // 提前终止
                    queue.offer(nb);
                }
            }
        }
        return -1;


    }
}
相关推荐
骄马之死2 小时前
SpringMVC + SpringBoot 核心知识点总结
java·spring boot·后端
郑洁文4 小时前
基于Spring Boot的流浪动物救助网站
java·spring boot·后端·毕设·流浪动物救助
螺丝钉code4 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
摇滚侠6 小时前
Maven 入门+高深 单一架构案例 54-59
java·架构·maven·intellij-idea
VidDown6 小时前
Webhook 调试器:让第三方回调“原形毕露”
java·开发语言·javascript·编辑器·postman
折哥的程序人生 · 物流技术专研6 小时前
Java 23 种设计模式:从踩坑到精通 | 原型模式 —— 克隆对象,深拷贝与浅拷贝的坑你踩过吗?
java·设计模式·架构·原型模式·单一职责原则
装不满的克莱因瓶6 小时前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty
程序员小羊!6 小时前
06Java 异常机制与常用类
java
weixin_523185327 小时前
Java基础知识总结(四):引用数据类型与参数传递机制
java·开发语言·python
sheeta19987 小时前
LeetCode 每日一题笔记 日期:2026.06.06 题目:2196. 根据描述创建二叉树
笔记·算法·leetcode