### Article directory

## subject

You have an array of integers, arr. you start at the first element of the array (subscript 0).

At each step, you can jump from subscript i to subscript:

i + 1 satisfies: i + 1 < arr.length

i - 1 satisfies: i - 1 > = 0

j: arr[i] == arr[j] and I! = j

Please return the minimum number of operations required to reach the subscript of the last element of the array.

Note: you cannot jump outside the array at any time.

Example 1:

Input: arr = [100, - 23, - 23404100,23,23,23,3404]

Output: 3

Explanation: then you need to jump 3 times, and the subscript is 0 -- > 4 -- > 3 -- > 9. Subscript 9 is the subscript of the last element of the array.

Example 2:

Input: arr = [7]

Output: 0

Explanation: it starts at the last element, so you don't need to jump.

Example 3:

Input: arr = [7,6,9,6,9,6,9,7]

Output: 1

Explanation: you can jump directly from subscript 0 to subscript 7, which is the last element of the array.

Tips:

1 <= arr.length <= 5 * 10^4

-10^8 <= arr[i] <= 10^8

## Solution 1 (double finger needle method)

Idea: the current solution uses two pointers to mark the in degree and out degree, that is, through the out degree to indicate whether the current is completed, and starts to enter the next iteration until there is a pointer to the last element to complete the task.

- The inCount in pointer is used to record the number of teams in the current layer, and the outCount out pointer is used to record the number of teams in the previous layer (the number of teams needed at present)
- There seems to be a three-level cycle, but each value is accessed only once; however, there are still multiple accesses to the value, but it is not modified, so the worst time complexity may be n!n!n! When building a dictionary, in order to prevent the worst situation, the index selection is from large to small, that is, if there are duplicate values, the later values are preferred.

- Time complexity: O(n2)
- Spatial complexity: O(n)

public class Solution { public int MinJumps(int[] arr) { Dictionary<int,List<int>> dict = new Dictionary<int,List<int>>(); for(int i=arr.Length-1;i>=0;i--) {//Record duplicate data for quick query if(!dict.ContainsKey(arr[i])) { dict.Add(arr[i],new List<int>()); } dict[arr[i]].Add(i); } bool []r = new bool[arr.Length]; int count = 0,idx=0,len = arr.Length - 1; int outCount,inCount = 1; bool flag = false; r[0] = true; Queue<int> q = new Queue<int>(); q.Enqueue(0); while(r[len] == false) { outCount = inCount; inCount = 0; while(outCount > 0) {//End of pointer counting idx = q.Dequeue(); outCount--; if(idx<len && r[idx+1] == false) { r[idx + 1] = true; q.Enqueue(idx+1); inCount++; if(idx + 1 == len) { return count+1; } } if(idx > 0 && r[idx-1] == false) { r[idx - 1] = true; q.Enqueue(idx-1); inCount++; if(idx - 1 == len) { return count+1; } } List<int> tmpList = dict[arr[idx]]; foreach(int i in tmpList) { if(arr[i] == arr[idx] && r[i] == false && i != idx) { r[i] = true; q.Enqueue(i); inCount++; if(i == len) { return count+1; } } } } count++; } return count; } }

## Solution 2 (violence method)

Idea: use array to record the level of each element when it is accessed. Since each element is accessed for the first time, and the number of times to be accessed for the next time is not less than the current value, only a maximum initial value needs to be paid, as long as it is not equal to the initial value, it means that it has been accessed.

- The initialization of array r that records the number of value accesses. Since the worst result is one backward access, that is, equal to the array length minus one, all elements except the first element are assigned the array length (any path to which the value is accessed is less than the array length)
- On the one hand, the r element is used to record the number of hops, on the other hand, it can also be used as an access identifier bit.
- When the end is encountered, you need to jump out in time, otherwise it will time out due to too many elements in the queue (you can also use a List to record whether it is in the queue for optimization). If not, the last test case will time out. The test case and source code are as follows:

- Time complexity: O(n2)
- Spatial complexity: O(n)
- Timeout cases that do not jump out: https://www.zhenxiangsimple.com/files/tech/testCase20200210.txt

public class Solution { public int MinJumps(int[] arr) { Dictionary<int,List<int>> dict = new Dictionary<int,List<int>>(); for(int i=arr.Length-1;i>=0;i--) {//Record duplicate data for quick query if(!dict.ContainsKey(arr[i])) dict.Add(arr[i],new List<int>()); dict[arr[i]].Add(i); } int []r = new int[arr.Length]; for(int i=1;i<r.Length;i++) r[i] = r.Length;//Default maximum Queue<int> q = new Queue<int>(); int idx; q.Enqueue(0); while(q.Count > 0) { idx = q.Dequeue(); foreach(int i in dict[arr[idx]]) { if(r[i] == r.Length) { r[i] = r[idx] + 1; q.Enqueue(i); } if(i == arr.Length - 1) break; } if(idx + 1 < arr.Length && r[idx+1] == r.Length) { r[idx+1] = r[idx] + 1; q.Enqueue(idx + 1); if(idx+1 == arr.Length - 1) break; } if(idx - 1 >= 0 && r[idx - 1] == r.Length) { r[idx-1] = r[idx] + 1; q.Enqueue(idx - 1); } } return r[arr.Length - 1]; } }