求解最大正方形面积 — leetcode 221. Maximal Square
2016-02-07 13:56
387 查看
本来也想像园友一样,写一篇总结告别 2015,或者说告别即将过去的羊年,但是过去一年发生的事情,实在是出乎平常人的想象,也不具有代表性,于是计划在今年 6 月份写一篇 "半年总结",希望不会忘记。羊年,还是以一道有意思的算法题来告别吧!
Maximal Square,又是一道有意思的题。给出一个二维数组,数组中的元素是 1 或者 0,求解最大的由 1 组成的正方形面积。
比如这样一个二维数组:
很显然最大的正方形面积为 2*2=4。
根据经验,一眼便看出这是一道 动态规划 题。我们用 dp[i][j] 表示以 matrix[i][j] 为右下角的最大全 1 正方形的边长,仔细思考,如何推得 dp[i][j] 的递推公式?
dp[i][j] 可以从三部分推得,首先是 dp[i-1][j-1],然后是 matrix[i][j] 左边的连续 1 的个数,然后是 matrix[i][j] 上面连续 1 的个数,这三部分取最小值。于是我们可以维护三个数组,dp[i][j] 表示以 matrix[i][j] 为右下角的全 1 正方形的边长,a[i][j] 表示从 matrix[i][j] 往左的连续 1 的个数,b[i][j] 表示从 matrix[i][j] 往上的连续 1 的个数。
可以推得(注意边界值):
需同时更新三个数组的值,完整代码可以参考 index_1.js。
当然这还不算完,继续优化。我们以 a 数组为例,其实 a 数组完全能用 dp 数组代替。
当 a[i][j-1] <= dp[i-1][j-1] 时,Math.min(dp[i-1][j-1], a[i][j-1]) 的结果就是 a[i][j-1],也就是 dp[i][j-1]
当 a[i][j-1] > dp[i-1][j-1] 时,Math.min(dp[i-1][j-1], a[i][j-1]) 的结果就是 dp[i-1][j-1]
所以 Math.min(dp[i-1][j-1], a[i][j-1]) 的结果也就是 dp[i-1][j-1], dp[i][j-1])。数组 b 同理。
所以程序可以将转移方程优化为:
完整代码可以参考 index_2.js。
今天是除夕,最后祝大家在新的一年里身体健康,心想事成!!最重要的还是身体健康,身体健康,身体健康!!!重要的事情说三遍!!!
Maximal Square,又是一道有意思的题。给出一个二维数组,数组中的元素是 1 或者 0,求解最大的由 1 组成的正方形面积。
比如这样一个二维数组:
1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0
很显然最大的正方形面积为 2*2=4。
根据经验,一眼便看出这是一道 动态规划 题。我们用 dp[i][j] 表示以 matrix[i][j] 为右下角的最大全 1 正方形的边长,仔细思考,如何推得 dp[i][j] 的递推公式?
dp[i][j] 可以从三部分推得,首先是 dp[i-1][j-1],然后是 matrix[i][j] 左边的连续 1 的个数,然后是 matrix[i][j] 上面连续 1 的个数,这三部分取最小值。于是我们可以维护三个数组,dp[i][j] 表示以 matrix[i][j] 为右下角的全 1 正方形的边长,a[i][j] 表示从 matrix[i][j] 往左的连续 1 的个数,b[i][j] 表示从 matrix[i][j] 往上的连续 1 的个数。
可以推得(注意边界值):
if (matrix[i][j] === '1') { dp[i][j] = Math.min(i && j ? dp[i - 1][j - 1] : 0, j ? a[i][j - 1] : 0, i ? b[i - 1][j] : 0) + 1; a[i][j] = j ? a[i][j - 1] + 1 : 1; b[i][j] = i ? b[i - 1][j] + 1 : 1; ans = dp[i][j] > ans ? dp[i][j] : ans; } else { dp[i][j] = a[i][j] = b[i][j] = 0; }
需同时更新三个数组的值,完整代码可以参考 index_1.js。
当然这还不算完,继续优化。我们以 a 数组为例,其实 a 数组完全能用 dp 数组代替。
当 a[i][j-1] <= dp[i-1][j-1] 时,Math.min(dp[i-1][j-1], a[i][j-1]) 的结果就是 a[i][j-1],也就是 dp[i][j-1]
当 a[i][j-1] > dp[i-1][j-1] 时,Math.min(dp[i-1][j-1], a[i][j-1]) 的结果就是 dp[i-1][j-1]
所以 Math.min(dp[i-1][j-1], a[i][j-1]) 的结果也就是 dp[i-1][j-1], dp[i][j-1])。数组 b 同理。
所以程序可以将转移方程优化为:
if (matrix[i][j] === '1') { dp[i][j] = Math.min(i && j ? dp[i - 1][j - 1] : 0, j ? dp[i][j - 1] : 0, i ? dp[i - 1][j] : 0) + 1; ans = dp[i][j] > ans ? dp[i][j] : ans; } else { dp[i][j] = 0; }
完整代码可以参考 index_2.js。
今天是除夕,最后祝大家在新的一年里身体健康,心想事成!!最重要的还是身体健康,身体健康,身体健康!!!重要的事情说三遍!!!
相关文章推荐
- Vim简明教程【CoolShell】转自http://blog.csdn.net/niushuai666/article/details/7275406 (飘过的小牛)
- HDU 5621 KK's Point
- Win10系统查看网络连接详细信息的方法
- Leetcode 322. Coin Change
- hdu KK's Steel【思维】【斐波那契数列应用】
- 1238 Substrings
- Activity
- 学习Hibernate源码——配置文件解析,SessionFactory创建
- [置顶] 宿主机-开发板设置NFS共享目录(1)
- 大数据IMF 传奇 8台设备如何实现免密码的SSH登录呢 ?脚本分发 解决方案
- 自学帝国CMS---网站搬家
- HDU3037 Saving Beans(Lucas定理+乘法逆元)
- BestCoder Round #71 (div.2)-KK's Steel(斐波那契数列)
- [Spring实战系列](12)Bean的自动装配
- 递推-hdu1041 Computer Transformation
- 在html在添加cookie和读取cookie
- hdu 1598 find the most comfortable road 枚举+并查集
- WMI技术介绍和应用——Instance/Method Provider
- python_简单的ssh客户端
- 大牛给的ACM进阶建议