力扣每日一题2022-01-21困难题:跳跃游戏IV


1345.跳跃游戏IV

题目描述

跳跃游戏IV


思路

BFS

记arr数组的长度为n。题目描述的数组可以等价于一个无向图,数组的每个元素为图的顶点,相邻下标的元素之间有一条无向边相连,所有值相等的元素之间也有无向边相连。每条边的权重都为1,即图为无权图。求从第一个元素到最后一个元素的最少操作数,就相当于求第一个元素到最后一个元素的最短路径长度。求无权图两点之间的最短距离可以用BFS求解,时间复杂度为O(V+E),V为图的顶点数,E为图的边数。
在此题中,V=n,E最多可以达到O(n^2)数量级,所以常规方法会超时。超时的原因主要是所有值相同的元素构成了一个稠密子图,普通的BFS会对这个稠密子图所有边都访问一次。但对于无权图的最短路径,这样的访问是不必要的。可以在第一次访问到这个子图中的某个节点时,将这个子图的所有未在队列中的节点都加入队列。在第二次访问这个子图的节点时,就不需要去考虑其他节点,因为所有结点都在队列中或者已被访问过。因此,需要先找出所有值相同的子图,用一个哈希表保存。在第一次把这个子图的所有节点放入队列后,把子图清空,就不会重复访问该子图的其它边。

Python实现

Python实现

class Solution:
    def minJumps(self, arr: List[int]) -> int:
        sameValueDict = defaultdict(list)
        for i, a in enumerate(arr):
            sameValueDict[a].append(i)
        visited = set()
        q = deque()
        q.append([0, 0])
        visited.add(0)
        while q:
            idx, step = q.popleft()
            if idx == len(arr) - 1:
                return step
            v = arr[idx]
            step += 1
            for i in sameValueDict[v]:
                if i not in visited:
                    q.append([i, step])
            del sameValueDict[v]
            if idx + 1 < len(arr) and (idx + 1) not in visited:
                visited.add(idx + 1)
                q.append([idx + 1, step])
            if idx - 1 >= 0 and (idx - 1) not in visited:
                visited.add(idx - 1)
                q.append([idx - 1, step])
Java实现

Java实现

class Solution {
    public int minJumps(int[] arr) {
        Map<Integer, List<Integer>> idxSameValue = new HashMap<Integer, List<Integer>>();
        for (int i = 0; i < arr.length; i++) {
            idxSameValue.putIfAbsent(arr[i], new ArrayList<Integer>());
            idxSameValue.get(arr[i]).add(i);
        }
        Set<Integer> visitedIndex = new HashSet<Integer>();
        Queue<int[]> queue = new ArrayDeque<int[]>();
        queue.offer(new int[]{0, 0});
        visitedIndex.add(0);
        while (!queue.isEmpty()) {
            int[] idxStep = queue.poll();
            int idx = idxStep[0], step = idxStep[1];
            if (idx == arr.length - 1) {
                return step;
            }
            int v = arr[idx];
            step++;
            if (idxSameValue.containsKey(v)) {
                for (int i : idxSameValue.get(v)) {
                    if (visitedIndex.add(i)) {
                        queue.offer(new int[]{i, step});
                    }
                }
                idxSameValue.remove(v);
            }
            if (idx + 1 < arr.length && visitedIndex.add(idx + 1)) {
                queue.offer(new int[]{idx + 1, step});
            }
            if (idx - 1 >= 0 && visitedIndex.add(idx - 1)) {
                queue.offer(new int[]{idx - 1, step});
            }
        }
        return -1;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值