• 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]];
        }
    };
    
  • 相关阅读:
    杰出人才项目管理的设计与实现
    企业人事信息管理系统开发与设计
    高等职业院校人事薪资管理系统的开发与实现
    基于UML的高校组织人事档案管理系统建模研究
    基于UML技术的电子商务系统设计
    人事管理系统的设计与实现
    文献随便目录4
    Qt 设置button互斥,一组button只能选中一个
    C++ 子类重写父类函数,子类调用重写函数,执行父类的函数还是子类的函数?
    QLabel 设置背景图片的方法和解决图片太大不能完显示的办法
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15832128.html
Copyright © 2020-2023  润新知