【leetcode】 跳跃游戏 IV

跳跃游戏IV

题目

给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。

每一步,你可以从下标 i 跳到下标 i + 1 、i - 1 或者 j :

i + 1 需满足:i + 1 < arr.length
i - 1 需满足:i - 1 >= 0
j 需满足:arr[i] == arr[j] 且 i != j
请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。

注意:任何时候你都不能跳到数组外面。

 

示例 1:

输入:arr = [100,-23,-23,404,100,23,23,23,3,404]
输出:3
解释:那你需要跳跃 3 次,下标依次为 0 --> 4 --> 3 --> 9 。下标 9 为数组的最后一个元素的下标。
示例 2:

输入:arr = [7]
输出:0
解释:一开始就在最后一个元素处,所以你不需要跳跃。
示例 3:

输入:arr = [7,6,9,6,9,6,9,7]
输出:1
解释:你可以直接从下标 0 处跳到下标 7 处,也就是数组的最后一个元素处。
 

提示:

1 <= arr.length <= 5 * 104
-108 <= arr[i] <= 108

思路

  • 拿到题的第一反应 是使用动态规划的方式进行接替
    即dp[i]表示第i个位置到达数组最后一个元素需要操作最少的步骤
    dp[i] = min(dp[i - 1] + 1, dp[i + 1] + 1, dp[j] + 1),其中arr[i] == arr[j] && i != j
    尝试了好久有一个用例一直无法通过,后来思考了一下 发现dp[i]的结果依赖于dp[i + 1],而dp[i + 1]的结果也依赖dp[i],在这种情况下无法使用动态规划解题(想到这点的时候还没意识到)。后来看了题解里大佬论证dp不可行的原因才意识到。
    题解大佬
  • 采用BFS + 剪枝,看代码吧。
  • 一开始确实是用了map进行剪枝,但是剪枝后没remove掉导致有个用例超时,这里记录一下吸取教训。

代码

    public int minJumps(int[] arr) {
        if (arr.length == 1) {
            return 0;
        }

        Map<Integer, List<Integer>> firstMap = new HashMap<>();

        for (int i = 0; i < arr.length; ++i) {
            int val = arr[i];
            if (!firstMap.containsKey(val)) {
                firstMap.put(val, new ArrayList<>());
            }
            firstMap.get(val).add(i);
        }

        Queue<Integer> idxQueue = new LinkedList<>();
        Set<Integer> visited = new HashSet<>();

        idxQueue.offer(0);
        visited.add(0);
        int step = 0;

        while (!idxQueue.isEmpty()) {
            int size = idxQueue.size();
            for (int k = 0; k < size; ++k) {
                int idx = idxQueue.poll();

                if (idx == arr.length - 1) {
                    return step;
                }

                if(idx - 1 >= 0 && !visited.contains(idx - 1)) {
                    idxQueue.offer(idx - 1);
                    visited.add(idx - 1);
                }


                if(idx + 1 < arr.length && !visited.contains(idx + 1)) {
                    idxQueue.offer(idx + 1);
                    visited.add(idx + 1);
                }

                // 跳着走
                if (firstMap.containsKey(arr[idx])) {
                    for (int i : firstMap.get(arr[idx])) {
                        if (arr[i] == arr[idx] && i != idx && !visited.contains(i)) {
                            idxQueue.offer(i);
                            visited.add(i);
                        }
                    }
                    firstMap.remove(arr[idx]);
                }

            }
            ++step;
        }
        return step;
    }

相关推荐

  1. LeetCode跳跃游戏 VI

    2024-04-14 07:10:05       33 阅读

最近更新

  1. 使用Spring Cloud构建微服务架构下的淘客返利系统

    2024-04-14 07:10:05       0 阅读
  2. TCP/IP协议族结构和协议

    2024-04-14 07:10:05       1 阅读
  3. 重读AI金典算法模型-GPT系列

    2024-04-14 07:10:05       1 阅读
  4. win10使用小技巧三

    2024-04-14 07:10:05       1 阅读
  5. 根据关键词query获取google_img(api方式)

    2024-04-14 07:10:05       1 阅读
  6. redis中的事务和mysql中的事务有什么区别?

    2024-04-14 07:10:05       1 阅读
  7. C# 构造函数依赖注入 使用out向外传递参数

    2024-04-14 07:10:05       1 阅读

热门阅读

  1. janus搭建

    2024-04-14 07:10:05       20 阅读
  2. libtorch中API介绍

    2024-04-14 07:10:05       48 阅读
  3. FFmpeg: 自实现ijkplayer播放器--07解复用线程设计

    2024-04-14 07:10:05       20 阅读
  4. 解决在 Ubuntu18.04 上安装 ffmpeg 失败的方法

    2024-04-14 07:10:05       52 阅读
  5. FFmpeg: 自实现ijkplayer播放器--08视频解码线程设计

    2024-04-14 07:10:05       16 阅读
  6. Flume配置案例@Source:文件,Channel+Sink:Kafka

    2024-04-14 07:10:05       20 阅读
  7. Python学习入门(3)—— 高级技巧

    2024-04-14 07:10:05       21 阅读