给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。
每一步,你可以从下标 i 跳到下标:
i + 1 满足:i + 1 < arr.length
i - 1 满足:i - 1 >= 0
j 满足:arr[i] == arr[j] 且 i != j
请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。
注意:任何时候你都不能跳到数组外面
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jump-game-iv
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution {
public int minJumps(int[] arr) {
int i,n=arr.length;
//当arr数组中的数少于2个,则不需要跳
if(arr.length<=1)
return 0;
//如果正好是两个或数组开头等于数组结束元素,则只需要跳一步
else if(arr[0]==arr[n-1]||arr.length<=2)
return 1;
//定义哈希列表,运用列表对应节点来减少运行时间
Map<Integer,List<Integer>>map=new HashMap<>();
//遍历数组,保存数组下标
for(i=0;i<n;i++){
if(!map.containsKey(arr[i]))
map.put(arr[i],new ArrayList<>());
map.get(arr[i]).add(i);
}
//从起点出发,存储可以到达的下标
Queue<Integer>q=new LinkedList<>();
q.offer(0);
//存储访问过的节点,用于减少访问次数
boolean[]visit=new boolean[n];
visit[0]=true;
//从起点开始进行遍历
for(int step=0;!q.isEmpty();step++){
for(int size=q.size();size>0;size--){
int startId=q.poll();
if(startId==n-1)
return step;
if(startId-1>=0&&!visit[startId-1]){
q.offer(startId-1);
visit[startId-1]=true;
}
if(startId+1<n&&!visit[startId+1]){
q.offer(startId+1);
visit[startId+1]=true;
}
if(map.containsKey(arr[startId])){
List<Integer>list=map.get(arr[startId]);
for(i=list.size()-1;i>=0;i--){
int id=list.get(i);
if(id==n-1)
return step+1;
if(id>=0&&!visit[id])
q.offer(id);
}
//移除访问过的节点
map.remove(arr[startId]);
}
}
}
return -1;
}
}