问题:
跳棋游戏。
在一维数组arr中,从index=0开始,
下一步可以跳到:(在数组范围内)
- index+1
- index-1
- index_j : arr[index_j]=arr[index]
求最快跳到最后一格arr.size()-1的位置,需要多少步。
Example 1: Input: arr = [100,-23,-23,404,100,23,23,23,3,404] Output: 3 Explanation: You need three jumps from index 0 --> 4 --> 3 --> 9. Note that index 9 is the last index of the array. Example 2: Input: arr = [7] Output: 0 Explanation: Start index is the last index. 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 index 0 to index 7 which is last index of the array. Example 4: Input: arr = [6,1,9] Output: 2 Example 5: Input: arr = [11,22,7,7,7,7,7,7,7,22,13] Output: 3 Constraints: 1 <= arr.length <= 5 * 104 -108 <= arr[i] <= 108
解法:BFS
状态:当前index
queue中保存该状态,visited中也存该状态,来防止重复。
选择:
- index+1
- index-1
- index_j : arr[index_j]=arr[index]
因此需要初始化构造index_j的所有取值。graph[arr[index]]
⚠️ 注意:本问题中数量级很大,需要考虑如何剪枝。
根据题意,如跳到 i 的位置后,下一步可选择所有 值==arr[i]的index。
这些index,其实也只能入队一次,尝试一次即可。
(由于本来queue的遍历就是按照层次从0开始,一次变大的,因此先入队的index,一定经过的步数较小
因此,可以在尝试入队一次所有的 index_j 后,直接删除相同arr[i]下的所有 index_j )。
下一次在找到相同的arr[i]值,去求 index_j 的时候,已经入队过,可以不需要入队检查。
代码参考:
1 class Solution { 2 public: 3 int n; 4 int minJumps(vector<int>& arr) { 5 unordered_map<int, vector<int>> graph;//arr[i], {i,j,...} 6 n = arr.size(); 7 for(int i=0; i<n; i++) { 8 graph[arr[i]].push_back(i); 9 } 10 unordered_set<int> visited; 11 queue<int>q; 12 int step = 0; 13 q.push(0); 14 visited.insert(0); 15 while(!q.empty()) { 16 int sz = q.size(); 17 for(int k=0; k<sz; k++) { 18 int cur = q.front(); 19 q.pop(); 20 //cout<<"pop: "<<cur<<endl; 21 if(cur==n-1) return step; 22 if(cur+1<n && visited.insert(cur+1).second) { 23 //cout<<"push:cur+1: "<<cur+1<<" step:"<<step<<endl; 24 q.push(cur+1); 25 } 26 if(cur-1>0 && visited.insert(cur-1).second) { 27 //cout<<"push:cur-1: "<<cur-1<<" step:"<<step<<endl; 28 q.push(cur-1); 29 } 30 for(int idx:graph[arr[cur]]) { 31 if(visited.insert(idx).second) { 32 //cout<<"push:idx: "<<idx<<" value:"<<arr[cur]<<" step:"<<step<<endl; 33 q.push(idx); 34 } 35 } 36 //cout<<"clear graph:"<<cur<<endl; 37 graph[arr[cur]].clear();//相同的值对应的index都加入过,去掉。 38 } 39 step++; 40 } 41 return n; 42 } 43 };