1345.跳跃游戏IV-LeetCode

难度:困难

目录

一、问题描述

二、解题思想

三、解题

1、判断极端情况

2、代码实现

四、总结


一、问题描述

这里直接采用的是leetcode上面的问题描述。

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

每一步,你可以从下标 i 跳到下标:

  • i + 1 满足:i + 1 < arr.length
  • i - 1 满足:i - 1 >= 0
  • j 满足:arr[i] == arr[j] 且 i != j

请你返回到达数组最后一个元素的下标处所需的 最少操作次数

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

下面给出示例:

提示:

  • 1 <= arr.length <= 5 * 10^4
  • -10^8 <= arr[i] <= 10^8

二、解题思想

        采用的BFS(宽度优先搜索)+DP(动态规划),将给的 arr 抽象成无向图。

例如:arr = [100,-23,-23,404,100,23,23,23,3,404] 可以抽象成下无向图

 那么问题就抽象成了从 0 下标以 最少的操作次数 跳跃至 arr.size()-1 下标处。

我们使用到的变量有以下:

  • hashTable:存储一个数字所对应的下标。如100对应的下标有 { 0, 4 }
  • MAX:无穷大、用来初始化 dist
  • dist:存储从 0 下标至第 x 个下标对应的最小步数 y dist[x] == MAX说明 x节点没有被访问过。
  • Q:队列,用来存储当前下标所能移动到的下标 从 0 开始 先pop(0) ,接着push(1) push(4)

开始循环:

  1. 将队首元素保存为 pre 并出队,将队首元素下标对应的步数保存为 steps
  2. 判断 pre 是否等于arr.size()-1 等于的话返回到达该节点对应的步数 steps
  3. 判断 pre下一下标的步数是否为MAX。是的话说明没有更新过到达该节点的步数 steps,更新到达该节点步数,并将该节点入队。
  4. 判断 pre上一下标的步数是否为MAX。是的话说明没有更新过到达该节点的步数 steps,更新到达该节点步数,并将该节点入队。
  5. 查看 pre是否还可以访问到其他节点,如果有更新到达该节点的步数,并将该节点入队。
  6. 清除hashTable[arr [ pre ] ],因为到此 arr[ pre ] 所对应的全部节点全部入队。

上面例子抽象的无向图所对应的 最少操作次数 路径为:

三、解题

1、判断极端情况

我这里判断了一下传入的 arr 大小是否为 1 arr 的首尾元素是否相等。

2、代码实现

    int minJumps(vector<int>& arr) {
        if(arr.size() == 1){
            return 0;
        }
        if(arr[0] == arr[arr.size()-1]){
            return 1;
        }
        const int MAX = 0xffffffff;
        int arrLength = arr.size();
        unordered_map<int,vector<int>> hashTable;
        //哈希表,存储一个数字有多少个对应得下标
        for(int i = arrLength-1; i >= 0; i--){
            hashTable[arr[i]].push_back(i);
        }
        //初始化解的容器
        vector<int> dist(arrLength,MAX);
        queue<int> Q;
        //dist[x] = y  means 到下标为x 需要y步
        dist[0] = 0;
        //初始化从 0 开始 查找
        Q.push(0);
        //队列不为空 就继续执行循环
        while(!Q.empty()){
            //pre 为队首元素 代表队首下标
            auto pre = Q.front(), steps = dist[pre];
            Q.pop();
            if(pre == arrLength-1){
                return steps;
            }
            if(pre+1 < arrLength && dist[pre+1] == MAX){
                Q.push(pre+1);
                dist[pre+1] = steps+1;
            }
            if(pre-1 >= 0 && dist[pre-1] == MAX){
                Q.push(pre-1);
                dist[pre-1] = steps + 1;
            }
            const auto list = hashTable[arr[pre]];
            for(auto it:list){
                if(dist[it] == MAX){
                    Q.push(it);
                    dist[it] = steps + 1;
                }
            }
            hashTable[arr[pre]].clear();
        }
        return -1;
        }

四、总结

        刚开始看到这题着实不知从何下手,摸索没头绪,然后看题解加上自己推到然后慢慢理解其中的意思,使用BFS 加上 DP不懂这个的话可能还是要摸索很长时间,希望这篇博客能够帮助到你来尽快理清头绪。

        如果对你有什么帮助,请star ♥ 一下,收藏一下,蟹蟹啦!👇👇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Alkaid_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值