Leetcode 1345. 跳跃游戏 IV(BFS)

给你一个整数数组 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

看题目发现没什么好的解决方法,那就只能爆搜了。因为操作次数要求最少,那么优先考虑BFS。直接裸搜必然会T,考虑如何优化:首先连续的一段相同的数可以压缩为头尾两个,这样不影响结果。例如[11,22,7,7,7,7,7,7,7,22,13]可以压缩为[11,22,7,7,22,13],正确性显然(因为一样的数没必要在里面反复跳),至于为什么不压缩为一个可以考虑样例[3,3,3,4]。还有一个优化就是所有值相同的数只需要遍历一次(BFS解最优的性质),可以用一个数组记忆化一下。同时注意到ai范围1e8还分正负,只能离散化或者map处理了,可以用unordered_map卡一下常不过没啥必要。其他细节见代码:

class Solution {
    #define pb push_back
    #define fi first
    #define se second 
    #define pii pair<int,int>
public:
    int n;
    unordered_map<int, vector<int> > mp;
    unordered_map<int, int> step;
    //一串连续的数字只需要保留头尾
    vector<int> a;
    queue<pii> q;
    bool vis[500005];
    void bfs() {
        queue<pii> q;
        q.push(make_pair(0, 0));
        memset(vis, 0, sizeof(vis));
        while(q.size()) {
            pii now = q.front();
            q.pop();
            step[a[now.fi]] = now.se;//所有value相同的点都会更新 而终点肯定是那组点里最后一个被更新的(往vector里放的时候是按照从前到后的顺序) 因此能保证正确性(例如对于样例1 2 2)
            if(now.fi == n - 1) break;
            if(now.fi == 0) step[a[now.fi]]++;
            if(now.fi - 1 >= 0 && step.find(a[now.fi - 1]) == step.end()) {
                q.push(make_pair(now.fi - 1, now.se + 1));
            }
            if(now.fi + 1 < n && step.find(a[now.fi + 1]) == step.end()) {
                q.push(make_pair(now.fi + 1, now.se + 1));
            }
            if(mp.find(a[now.fi]) == mp.end()) continue;
            if(vis[now.fi]) continue;
            for(auto p : mp[a[now.fi]]) {
                if(p == now.fi) continue;
                q.push(make_pair(p, now.se + 1));
                vis[p] = 1;//这里可以防止tle
            }
        }
    }
    int minJumps(vector<int>& arr) {
        int tn;
        tn = n = arr.size();
        int dup = 0;
        for(int i = 0; i < n; i++) {
            if(i == 0) {
                a.pb(arr[i]);
            } else {
                if(arr[i] != arr[i - 1]) {
                    if(i - 2 >= 0 && arr[i - 1] == arr[i - 2]) a.pb(arr[i - 1]);
                    a.pb(arr[i]);
                }
            }
        }
        if(n - 2 >= 0 && arr[n - 1] == arr[n - 2]) a.pb(arr[n - 1]);
        n = a.size();
        for(int i = 0; i < a.size(); i++) {
            mp[a[i]].pb(i);
        }
        bfs();
        if(tn == 1) return 0;
        else if(a[0] == a[n - 1]) return 1;
        else return step[a[n - 1]];
    }
};
上一篇:学习笔记20220124 读pointnet++


下一篇:第五节