本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
1345.跳跃游戏 IV
题目大意
给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。
每一步,你可以从下标 i 跳到下标:
i + 1满足:i + 1 < arr.lengthi - 1满足:i - 1 >= 0j满足:arr[i] == arr[j]且i != j
请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。
注意:任何时候你都不能跳到数组外面。
样例
数据规模
思路
考虑一般的BFS做法:数组长度为,构造一个无向图:起点为0,终点为,任意相邻的节点可以建边(比如与,与可以建边),相同元素之间可以互相连边。边权都是1,就相当于这是一个无权图。从起点0出发,到终点,使用BFS求解,时间复杂度,但是可能到达 ,这必然会导致超时(所有元素相同)。
但实际上没必要访问每一条边,只需要保证每一个点都访问到就行,并且每个点之访问一次。在第一次访问到这个子图中的某个节点时,即会将这个子图的所有其他未在队列中的节点都放入队列。在第二次访问到这个子图中的节点时,就不需要去考虑这个子图中的其他节点了,因为所有其他节点都已经在队列中或者已经被访问过了。所以维护一个类型的记录相同元素,在维护数组保证每个节点之访问一次。然后BFS求解即可。时间复杂度
代码
class Solution {
public:
int minJumps(vector<int>& arr) {
unordered_map<int,vector<int> >val;
for(int i=0;i<arr.size();i++){
val[arr[i]].push_back(i);
}
queue<pair<int,int>>q;
q.push(make_pair(0,0));
vector<int>vis(50000+50,0);
int n=arr.size();
while(!q.empty()){
pair<int,int>x=q.front();q.pop();
if(x.first==n-1)return x.second;
if(vis[x.first])continue;
vis[x.first]=1;
if(val.count(arr[x.first])){
for(auto it:val[arr[x.first]]){
q.push(make_pair(it,x.second+1));
}
val.erase(arr[x.first]);
}
if(x.first-1>=0&&!vis[x.first-1]){
q.push(make_pair(x.first-1,x.second+1));
}
if(x.first+1<=n-1&&!vis[x.first+1]){
q.push(make_pair(x.first+1,x.second+1));
}
}
return n-1;
}
};