本文共 2637 字,大约阅读时间需要 8 分钟。
在一个由0和1组成的二维矩阵中,找到只包含1的最大正方形并返回其面积。这个问题可以通过两种主要方法解决:暴力求解法和动态规划法。以下是对这两种方法的详细分析和实现。
思路:遍历矩阵中的每一个1,尝试以其为左上角,扩展出最大的全1的正方形。具体来说,对于每一个1的位置(i, j),从边长1开始,逐步扩展到更大的边长,直到遇到0或者矩阵边界。
实现步骤:
优点:直接且简单,适合小规模矩阵。缺点:时间复杂度较高,尤其在大矩阵下效率低。
思路:创建一个辅助矩阵f,其中f[i][j]表示从(0,0)到(i,j)的位置所形成的最大的全1的正方形的边长。递推公式为f[i][j] = 1 + min(f[i-1][j], f[i-1][j-1], f[i][j-1])。遍历矩阵,逐步计算每个位置的f值,最后找到最大的f值并返回其平方。
实现步骤:
优点:时间复杂度为O(mn),空间复杂度为O(mn),效率更高。缺点:需要额外的空间来保存f矩阵。
fun maximalSquare(matrix: Array): Int { var ans = 0 val m = matrix.size if (m == 0) return 0 val n = matrix[0].size val lenBound = Math.min(m, n) for (i in 0 until m) { for (j in 0 until n) { if (matrix[i][j] == '1') { var squareLength = 1 var flag = true while (i + squareLength < m && j + squareLength < n && flag && squareLength <= lenBound) { for (k in i..(i + squareLength)) { for (t in j..(j + squareLength)) { if (matrix[k][t] == '0') { flag = false break } } if (!flag) break } if (flag) squareLength++ } ans = Math.max(ans, squareLength) } } } return ans * ans}
fun maximalSquareDP(matrix: Array): Int { var ans = 0 val m = matrix.size if (m == 0) return 0 val n = matrix[0].size val f = Array(m + 1) { IntArray(n + 1) { 0 } } for (i in 1..m) { for (j in 1..n) { if (matrix[i - 1][j - 1] == '1') { val minix = Math.min(f[i - 1][j - 1], f[i - 1][j]) val minix2 = Math.min(f[i][j - 1], minix) f[i][j] = 1 + minix2 ans = Math.max(ans, f[i][j]) } } } return ans * ans}
val matrix = arrayOf( charArrayOf('1', '1', '1', '1', '1', '1', '1', '1'), charArrayOf('1', '1', '1', '1', '1', '1', '1', '0'), charArrayOf('1', '1', '1', '1', '1', '1', '1', '0'), charArrayOf('1', '1', '1', '1', '1', '0', '0', '0'), charArrayOf('0', '1', '1', '1', '1', '0', '0', '0'))val ans = maximalSquareDP(matrix)println("ans=$ans") // ans=16 两种方法各有优劣。动态规划法在效率上更优,适合大规模矩阵,而暴力求解法实现简单,适合小规模矩阵。选择哪种方法取决于具体需求和矩阵的尺寸。
转载地址:http://uhma.baihongyu.com/