原题传送门
1345. 跳跃游戏 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
class Solution {
public:
int minJumps(vector<int>& arr) {
queue<int> q;
int n = arr.size();
vector<bool> vis(n, false);
vector<int> dis(n, n + 5);
dis[0] = 0;
unordered_map<int, vector<int>> mp;
for (int i = 0; i < n; i++) {
mp[arr[i]].push_back(i);
}
q.push(0);
while (!q.empty()) {
int now = q.front();
q.pop();
if (vis[now])
continue;
vis[now] = true;
if (now + 1 < n && dis[now + 1] > dis[now] + 1) {
q.push(now + 1);
dis[now + 1] = dis[now] + 1;
}
if (now - 1 >= 0 && dis[now - 1] > dis[now] + 1) {
q.push(now - 1);
dis[now - 1] = dis[now] + 1;
}
for (int& j : mp[arr[now]]) {
if (now != j && dis[j] > dis[now] + 1) {
q.push(j);
dis[j] = dis[now] + 1;
}
}
mp[arr[now]].clear();
}
return dis[n - 1];
}
};