1345. 跳跃游戏 IV

题目

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

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

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

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

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

来源:力扣(LeetCode)


解答

遍历时,有三个方向,一个是向左,一个是向右,一个是跳向等值的数。

从头开始进行BFS即可,同时利用哈希表来遍历等值的元素。

具体代码及思路如下:

class Solution {
public:
    int minJumps(vector<int> &arr) {
        int n = arr.size();
        unordered_map<int, vector<int>> mp; // 记录相同值所包含的下标都有几个
        vector<int> all(n, -1); // 记录每一个位置最小步数
        queue<int> q; // 记录遍历内容

        // 将arr所有值对应下标记录到哈希表中,通过倒序记录,保证map先访问的是同值的最后一个元素
        for (int i = n - 1; i >= 0; --i) {
            mp[arr[i]].push_back(i);
        }

        all[0] = 0;   // 起止点在0,所以第一个值步数为0
        q.push(0); // 从第0个下标开始遍历,将其放入队列

        // 队列不空,表示未遍历完或未达到最后一个值
        while (!q.empty()) {
            // 元素出队,表示当前遍历到的元素
            auto cur = q.front(); // 当前遍历下标
            q.pop();

            if (cur == n - 1) {
                return all[cur];
            }

            // 检查右侧元素
            // == -1 表示未到达过
            if (cur + 1 < n && all[cur + 1] == -1) {
                q.push(cur + 1);
                all[cur + 1] = all[cur] + 1;
            }

            // 左侧元素
            if (cur - 1 >= 0 && all[cur - 1] == -1) {
                q.push(cur - 1);
                all[cur - 1] = all[cur] + 1;
            }

            // 等值元素
            auto same = mp[arr[cur]];
            for (auto tmp: same) {
                if (all[tmp] == -1) {
                    q.push(tmp);
                    all[tmp] = all[cur] + 1;
                }
            }

            // 将等值元素都删除,因为已经更新过步数了,
            // 如果后续还遇到该值,更新步数一定大于当前更新值(这样做是错误的)
            // 所以直接从哈希表中去除
            mp.erase(arr[cur]);
        }
        return -1;
    }
};

我的力扣每日一题 文章被收录于专栏

就是力扣每日一题的记录,解法可能存在参考,但一定是我自己理解和口述的。 题解更注重理解,而不是为了缩短代码行数,为了精简而精简。

全部评论

相关推荐

09-21 21:14
门头沟学院
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务