题目

类型:广度优先搜索
image.png

解题思路

1、使用「哈希表」记录某个值有哪些下标
2、进行BFS,假如当前走到的位置为 t,将 t - 1、t + 1 和与 arr[t] 等值的位置进行入队,为了防止重复同队使用 dist 数组记录到达某个位置的最小步数(初始化为 INF),只有 dist[ne] 为 INF 时,该点没有被遍历过,可以入队并更新最小步数。
3、光使用 dist 还不能确保复杂度为 O(n),因为每次都需要遍历与 arr[t] 等值的下标,为确保等值下标的遍历只会发生一次,需要在将等值下标添加到队列后,将 arr[t] 从哈希表中移除
首次检索到 arr[t] 值时,必然是最小步数,记为 step ,此时 BFS 做法将其他等值下标距离更新为 step + 1

  • 若 arr[t] 与结尾元素值相等,且 t 为 n - 1,此时 step 即是答案;
  • 若 arr[t] 与结尾元素值相等,但 t 不为 n - 1,此时会再跳一步到达结尾位置,即 step + 1 为答案。那么是否可能存在使用比 step + 1 更小的步数,也能到达结尾的位置呢?可能存在,但如果最后是通过「等值跳」到达结尾位置的话,不可能存在比 step + 1 更小的步数。由于我们每次加入等值时都会进行哈希表的移除,因此到达 t 的方式不可能是「等值跳」,而只能是「前后跳」。
    • 假设是通过前跳到达位置 t,即点分布如图,步数满足等于 step + 1:

image.png

  • 假设是通过后跳到达位置 t,即点分布如图,步数满足「如果是等值跳到达结尾,步数为 step + 1」:

    image.png
    综上,如果 n - 1 是经过「等值跳」加入队列的话,起所能达到的最小步数必然为发起点 t 的最小步数 +1。
    也就是说,即使首次等值跳,加入队列后会将其从哈希表中进行移除,正确性也是可以保证的。
    基于此,可以额外增加一个 trick,就是在构建哈希表的时候,使用「倒序」的形式构建等值下标列表,这样可以确保如果最后位置是通过「等值跳」而来是,能够优先出队。

代码

  1. class Solution {
  2. public int minJumps(int[] arr) {
  3. Map<Integer, List<Integer>> idxSameValue = new HashMap<Integer, List<Integer>>();
  4. for (int i = 0; i < arr.length; i++) {
  5. idxSameValue.putIfAbsent(arr[i], new ArrayList<Integer>());
  6. idxSameValue.get(arr[i]).add(i);
  7. }
  8. Set<Integer> visitedIndex = new HashSet<Integer>();
  9. Queue<int[]> queue = new ArrayDeque<int[]>();
  10. queue.offer(new int[]{0, 0});
  11. visitedIndex.add(0);
  12. while (!queue.isEmpty()) {
  13. int[] idxStep = queue.poll();
  14. int idx = idxStep[0], step = idxStep[1];
  15. if (idx == arr.length - 1) {
  16. return step;
  17. }
  18. int v = arr[idx];
  19. step++;
  20. if (idxSameValue.containsKey(v)) {
  21. for (int i : idxSameValue.get(v)) {
  22. if (visitedIndex.add(i)) {
  23. queue.offer(new int[]{i, step});
  24. }
  25. }
  26. idxSameValue.remove(v);
  27. }
  28. if (idx + 1 < arr.length && visitedIndex.add(idx + 1)) {
  29. queue.offer(new int[]{idx + 1, step});
  30. }
  31. if (idx - 1 >= 0 && visitedIndex.add(idx - 1)) {
  32. queue.offer(new int[]{idx - 1, step});
  33. }
  34. }
  35. return -1;
  36. }
  37. }