Leetcode周賽167

第一題直接模擬,第二題可以手動打表。

5285. 元素和小於等於閾值的正方形的最大邊長

在這裏插入圖片描述
\quad顯然,這是一個矩陣前綴和+二分。如果不用二分也能果,時間複雜度爲O(n3)=2.7107O(n^3)=2.7*10^7,使用二分後時間複雜度爲O(n2logn)=7.4105O(n^2logn)=7.4*10^5,我們使用加二分的方法去做。(一般O(n3)O(n^3)的極限在n=500n=500左右)。
\quad矩陣前綴和模板;二分查找最後一個小於等於和第一個大於等於某對象的數組元素位置模板

class Solution {
public:
    int bian(vector<vector<int>>& mat, int x)
    {
        int m = mat.size(), n = mat[0].size();
        int res = 0x3f3f3f3f;
        for(int i = 1; i <= m-x; i++)
            for(int j = 1; j <= n-x; j++)
            {
                int temp = mat[i+x-1][j+x-1]-mat[i-1][j+x-1]-mat[i+x-1][j-1]+mat[i-1][j-1];
                res = min(res, temp);
            }
        return res;
    }
    int maxSideLength(vector<vector<int>>& mat, int threshold) {
        int m = mat.size(), n = mat[0].size();
        // 用於提前判斷不存在這樣的子方陣
        bool flag = false;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++)
                if(mat[i][j]<=threshold) flag = true;
        if(!flag) return 0;
        // p爲矩陣前綴和
        vector<vector<int>> p(m+1, vector<int>(n+1, 0));
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
                p[i][j] += p[i-1][j]+p[i][j-1]-p[i-1][j-1]+mat[i-1][j-1];
        // 二分得到答案
        int l = 0, r = min(m, n), mid = 1;
        while(l<=r)
        {
            mid = l+r>>1;
            if(bian(p, mid)>threshold) r = mid-1;
            else l = mid+1;
        }
        return l-1;
    }
};

5286. 網格中的最短路徑

在這裏插入圖片描述
\quad這是一個帶可清除障礙的BFS問題,一共就mnkm*n*k種狀態,在隊列中維護座標x,y,消除的障礙數k和當前步數step即可。整體時間複雜度爲O(mnk)=404=2.56106O(m*n*k)=40^4=2.56*10^6

class Solution {
public:
    int vis[41][41][1601];  // 標記當前狀態(x, y, k)是否被訪問
    int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};  // 四個方向
    int shortestPath(vector<vector<int>>& grid, int k) {
        int m = grid.size(), n = grid[0].size();
        memset(vis, 0, sizeof(vis));
        queue<vector<int>> q;
        q.push({0, 0, 0, 0}); // {x, y, 已消除的障礙數k, 當前步數step}
        vis[0][0][0] = 1;
        while(!q.empty())
        {
            vector<int> now = q.front();
            q.pop();
            if(now[0]==m-1 && now[1]==n-1) return now[3];
            for(int i = 0; i < 4; i++)
            {
                vector<int> t = now;
                int x = t[0]+dx[i], y = t[1]+dy[i];
                if(x<0 || x>=m || y<0 || y>=n) continue;
                if(grid[x][y]==1) t[2]++;
                if(t[2]>k || vis[x][y][t[2]]==1) continue;
                vis[x][y][t[2]] = 1;
                q.push({x, y, t[2], t[3]+1});
            }
        }
        return -1;  // 無法到達
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章