LeetCode-764. 最大加号标志【动态规划,二维数组】
- 题目描述:
 - 解题思路一:动态规划。用一个n*n的数组记录每个点上下左右方向上为1的最小值。最后ans返回数组中最大的加号。
 - 解题思路二:优化1。
 - 解题思路三:0
 
题目描述:
在一个 n x n 的矩阵 grid 中,除了在数组 mines 中给出的元素为 0,其他每个元素都为 1。mines[i] = [xi, yi]表示 grid[xi][yi] == 0
返回 grid 中包含 1 的最大的 轴对齐 加号标志的阶数 。如果未找到加号标志,则返回 0 。
一个 k 阶由 1 组成的 “轴对称”加号标志 具有中心网格 grid[r][c] == 1 ,以及4个从中心向上、向下、向左、向右延伸,长度为 k-1,由 1 组成的臂。注意,只有加号标志的所有网格要求为 1 ,别的网格可能为 0 也可能为 1 。
示例 1:
 
 输入: n = 5, mines = [[4, 2]]
 输出: 2
 解释: 在上面的网格中,最大加号标志的阶只能是2。一个标志已在图中标出。
示例 2:
 
 输入: n = 1, mines = [[0, 0]]
 输出: 0
 解释: 没有加号标志,返回 0 。
提示:
1 <= n <= 500
 1 <= mines.length <= 5000
 0 <= xi, yi < n
 每一对 (xi, yi) 都 不重复
 https://leetcode.cn/problems/largest-plus-sign/
解题思路一:动态规划。用一个n*n的数组记录每个点上下左右方向上为1的最小值。最后ans返回数组中最大的加号。
class Solution {
public:
    int orderOfLargestPlusSign(int n, vector<vector<int>>& mines) {
        vector<vector<int>> dp(n, vector<int>(n, n));//初始化一个所有值全为n的二维网格,因为遍历是取min
        unordered_set<int> banned;//记录为0的点
        for (auto &&vec : mines) banned.emplace(vec[0] * n + vec[1]);
        int ans = 0;
        for (int i = 0; i < n; i++) {
            int count = 0;
            /* left */
            for (int j = 0; j < n; j++) {
                if (banned.count(i * n + j))count = 0;
                else count++;
                dp[i][j] = min(dp[i][j], count);
            }
            count = 0;
            /* right */ 
            for (int j = n - 1; j >= 0; j--) {
                if (banned.count(i * n + j)) count = 0;
                else count++;
                dp[i][j] = min(dp[i][j], count);
            }
        }
        for (int i = 0; i < n; i++) {
            int count = 0;
            /* up */
            for (int j = 0; j < n; j++) {
                if (banned.count(j * n + i)) count = 0;
                else count++;
                dp[j][i] = min(dp[j][i], count);
            }
            count = 0;
            /* down */
            for (int j = n - 1; j >= 0; j--) {
                if (banned.count(j * n + i)) count = 0;
                else count++;
                dp[j][i] = min(dp[j][i], count);
                ans = max(ans, dp[j][i]);//ans取最大的加号
            }
        }
        return ans;
    }
};
 
时间复杂度:O(n2)
 空间复杂度:O(n2)
解题思路二:优化1。
很简单,memset是一个字节一个字节设置的,取要赋的值的后8位二进制进行赋值。
1的二进制是(00000000 00000000 00000000 00000001),取后8位(00000001),int型占4个字节,当初始化为1时,它把一个int的每个字节都设置为1,也就是0x01010101,二进制是00000001 00000001 00000001 00000001,十进制就是16843009。
之所以输入0,-1时正确,纯属巧合。
0,二进制是(00000000 00000000 00000000 00000000),取后8位(00000000),初始化后00000000 00000000 00000000 00000000结果是0
 -1,负数在计算机中以补码存储,二进制是(11111111 11111111 11111111 11111111),取后8位(11111111),则是11111111 11111111 11111111 11111111结果也是-1
总结:memset()只有在初始化-1,0时才会正确。想要初始化为其他值,就乖乖的DIY吧!
 memset 函数适合初始化 0 或 -1,如果是其他值,还是老老实实用 for 循环吧。
class Solution {
public:
    int orderOfLargestPlusSign(int N, vector<vector<int>>& mines) {
        if (mines.size() == N * N) return 0;
        if (mines.size() > N * N - 5) return 1;
        int grid[N][N];
        int arm[N][N][4];
        // set all the value of grid to be "1", this is a trick to use "-1"
        memset(grid, -1, sizeof(grid));
        // set all the value of arm to be "0"
        memset(arm, 0, sizeof(arm));
        for (auto& v : mines) {
            grid[v[0]][v[1]] = 0;
        }
        for (int i = 0; i < N; ++i) {
            for (int j = 0; j < N; ++j) {
                if (grid[i][j] == 0) continue;
                arm[i][j][0] = 1 + ((i > 0) ? arm[i - 1][j][0] : 0);
                arm[i][j][1] = 1 + ((j > 0) ? arm[i][j - 1][1] : 0);
            }
        }
        for (int i = N - 1; i >= 0; --i) {
            for (int j = N - 1; j >= 0; --j) {
                if (grid[i][j] == 0) continue;
                arm[i][j][2] = 1 + ((i < N - 1) ? arm[i + 1][j][2] : 0);
                arm[i][j][3] = 1 + ((j < N - 1) ? arm[i][j + 1][3] : 0);
            }
        }
        int res = 0;
        for (int i = 0; i < N; ++i) {
            for (int j = 0; j < N; ++j) {
                if (grid[i][j] == 0) continue;
                int s = min(min(arm[i][j][0], arm[i][j][1]), min(arm[i][j][2], arm[i][j][3]));
                res = max(res, s);
            }
        }
        return res;
    }
};
 
时间复杂度:O(n2)
 空间复杂度:O(n2)
解题思路三:0
                












![[Python]字符串常用操作与方法](https://img-blog.csdnimg.cn/b866807aef9941c9a2255576c7151368.png)





