• LeetCode·每日一题·764.最大加号标志·动态规划


    作者:小迅
    链接:https://leetcode.cn/problems/largest-plus-sign/solutions/1958443/dong-tai-gui-hua-zhu-shi-chao-ji-xiang-x-nxil/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 

    题目

     

    示例

     

    思路

    题目要求返回给定数组中的最大 '+' 的长度,其中 '+' 的有效元素为 1 ,无效元素为 0, 简单来说就是 1 能组成的 '+' 最长度

    第一想法是递归暴力搜索,给定大小为 n 的二维数组,那么我们就构造一个 n 的二维数组,初始化为 1,然后将 mines 中的 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子元素 分开推导,每一次只推导一个 或者 二个 或者 更多,具体的话肯定是在最优的情况下推导更多的子元素

    具体实现看代码,注释超级详细

    官方的是将 赋0操作 加入了 哈希表 每次枚举一个位置时,写查询哈希表当前位置是否为 0,再进行之后的操作,使用哈希表的优势在于当 mines 和大时,可以减少赋值的时间

    代码

    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. }
    54. 作者:小迅
    55. 链接:https://leetcode.cn/problems/largest-plus-sign/solutions/1958443/dong-tai-gui-hua-zhu-shi-chao-ji-xiang-x-nxil/
    56. 来源:力扣(LeetCode)
    57. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    FreeRTOS最全教程(目录)
    JS备忘录
    如何判断从本机上传到服务器的文件数据内容是一致的?用md5加密算法!
    前端面试宝典React篇06 setState 是同步更新还是异步更新?
    计算机毕业设计JavaWeb端校园报修系统(源码+系统+mysql数据库+lw文档)
    Docker 容器文件(数据)共享
    labview卸载重装碰到的问题
    Node.js详解
    SSH指定用户登录与限制
    [JAVEee]SpringBoot项目的创建
  • 原文地址:https://blog.csdn.net/m0_64560763/article/details/127763888