• 764、最大加号标志


    在一个 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,无效元素为0,简单来说就是1能组成的‘+’的最大长度。

    对于任意一个位置,能够组成‘+’的最大长度取决于上下左右方向的最小长度,那么对于任意一个点:

    • dp[i][j] = MIN(dp[i-1][j],dp[i+1][j],dp[i][j+1],dp[i][j-1]) + 1,其中 dp[i][j] 表示当前位置 1 的个数

    必然满足该公式,但如何进行遍历?对于任意一个点,我们必须先知道上下左右才能推导当前位置,将问题简单化:

    • 如果当前节点 dp[i][j] = MIN(dp[i-1][j],dp[i][j-1]) + 1 我们只需要从头开始推导就可以推导出 dp[i][j]
    • 如果当前节点 dp[i][j] = MIN(dp[i+1][j],dp[i][j+1]) + 1 我们只需要从尾开始推导就可以推导出 dp[i][j]

    我们可以将每一个dp[i][j]所需要的dp子元素分开推导,每一次只推导一个或者两个或者更多,在最优的情况下推导更多的子元素。

    1. #define MIN(a, b) ((a) < (b) ? (a) : (b))
    2. #define MAX(a, b) ((a) > (b) ? (a) : (b))
    3. int orderOfLargestPlusSign(int n, int** mines, int minesSize, int* minesColSize){
    4. int dp[n][n];
    5. memset(dp, -1, sizeof(dp));
    6. int max = 0;
    7. for (int i = 0; i < minesSize; i++) {
    8. dp[mines[i][0]][mines[i][1]] = 0;
    9. }//初始化变量并赋值 0
    10. for (int i = 0; i < n; i++) {//枚举行子元素
    11. for (int j = 0; j < n; j++) {//第一次先初始化,当然也可以定义dp数组时初始化,都差不多
    12. if ((i == 0 || j == 0 || i == n-1 || j == n-1) && dp[i][j] != 0) {
    13. dp[i][j] = 1;
    14. max = 1;
    15. continue;
    16. }
    17. if (dp[i][j] != 0) {//行处理,dp[i][j-1] + 1;
    18. dp[i][j] = dp[i][j-1] + 1;
    19. }
    20. }
    21. if (i == 0 || i == n-1) {
    22. continue;
    23. }
    24. int count = 0;
    25. for (int j = n - 1; j >= 0; j--) {//行处理,相当于dp[i][j+1] + 1;
    26. if (dp[i][j] == 0) count = 0;
    27. if (dp[i][j] != 0) {
    28. ++count;
    29. dp[i][j] = MIN(dp[i][j], count);
    30. }
    31. }
    32. }
    33. for (int j = 1; j < n-1; j++) {//枚举列子元素
    34. int count = 0;
    35. for (int i = 0; i < n; i++) {//列处理,边界就不需要处理了,相当于dp[i-1][j]
    36. if (dp[i][j] == 0) count = 0;
    37. if (dp[i][j] != 0) {
    38. ++count;
    39. dp[i][j] = MIN(dp[i][j], count);
    40. }
    41. }
    42. count = 0;
    43. for (int i = n-1; i >= 0; i--) {//相当于dp[i+1][j]
    44. if (dp[i][j] == 0) count = 0;
    45. if (dp[i][j] != 0) {
    46. ++count;
    47. dp[i][j] = MIN(dp[i][j], count);
    48. }
    49. max = MAX(max, dp[i][j]);
    50. }
    51. }
    52. return max;
    53. }
  • 相关阅读:
    Qt基础之四十六:Qt界面中嵌入第三方程序的一点心得
    RocketMQ特性--事务消息是个啥,咋发出去的呢?
    力扣--三数之和
    屡破纪录|Hubble数据库又获2022全球数字经济大会背书 数据库赛道同类选优入选 “数字经济产业创新成果”
    centos 编译安装的php多版本 切换
    手把手实操|深度剖析电商贷款风控相关细节(电商贷模型)
    常见数据类型的占用字节数以及类型转换需要注意的事项
    LCR 122.路径加密
    出差学知识No1:制作一个shell脚本在正式命令执行前运行
    跨境电商卖家应该知道的3个社交媒体营销策略
  • 原文地址:https://blog.csdn.net/weixin_59179454/article/details/127766213