2021-06-26:给定一个只有0和1组成的二维数组,返回边框全是1的最大正方形面积。

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-06-26:给定一个只有0和1组成的二维数组,返回边框全是1的最大正方形面积。相关的知识,希望对你有一定的参考价值。

2021-06-26:给定一个只有0和1组成的二维数组,返回边框全是1的最大正方形面积。

福大大 答案2021-06-26:

1.自然智慧。遍历每个点,复杂度是O(N2)。每个点往右下看的从1到n正方形,复杂度是O(N),每个正方形,判断边框是否为1,复杂度是O(N)。所以总体时间复杂度是O(N4),额外空间复杂度是O(1)。

2.每个正方形的边框是否为1的优化。时间复杂度可以优化成O(1)。准备两个二维数组。一个二维数组,记录dpToRight[i][j],表示当前点往右看的1的个数。另一个二维数组,记录dpToDown[i][j],表示当前点往下看的1的个数。将近一天的研究,以为时间复杂度可以优化成O(N2),但实际上并不能,至少我目前没想出来。时间复杂度是O(N3),额外空间复杂度是O(N**2)。

代码用golang编写。代码如下:

package main

import (
    "fmt"
)

func main() {
    grid := [][]int{
        {0, 1, 1, 1, 1, 1, 1, 0},
        {1, 1, 1, 1, 1, 1, 1, 1},
        {1, 0, 1, 1, 1, 0, 1, 1},
        {1, 1, 1, 1, 0, 1, 1, 1},
        {1, 0, 1, 0, 0, 1, 1, 1},
        {0, 1, 1, 1, 1, 0, 1, 1},
    }
    largest1BorderedSquare1(grid)
    largest1BorderedSquare2(grid)
}

func printGrid(grid [][]int) {
    return
    N := len(grid)
    M := len(grid[0])
    for i := 0; i < N; i++ {
        for j := 0; j < M; j++ {
            fmt.Print(grid[i][j], " ")
        }
        fmt.Println("")
    }
    fmt.Println("--------")
}

func largest1BorderedSquare1(grid [][]int) int {
    ans := 0
    N := len(grid)
    M := len(grid[0])
    ans = largest1BorderedSquare11(grid)

    gridCopy := make([][]int, N)
    for i := 0; i < N; i++ {
        gridCopy[i] = make([]int, M)
    }
    //左右翻转
    for i := 0; i < N; i++ {
        for j := 0; j < M; j++ {
            gridCopy[i][j] = grid[i][M-j-1]
        }
    }
    ans = getMax(ans, largest1BorderedSquare11(gridCopy))

    //上下翻转
    for i := 0; i < N; i++ {
        for j := 0; j < M; j++ {
            gridCopy[i][j] = grid[N-i-1][j]
        }
    }
    ans = getMax(ans, largest1BorderedSquare11(gridCopy))

    //左右翻转,上下翻转
    for i := 0; i < N; i++ {
        for j := 0; j < M; j++ {
            gridCopy[i][j] = grid[N-i-1][M-j-1]
        }
    }
    ans = getMax(ans, largest1BorderedSquare11(gridCopy))

    if ans > 0 {
        ans = largest1BorderedSquare22(grid, ans)
    }

    fmt.Println(ans * ans)
    return ans * ans
}

func largest1BorderedSquare11(grid [][]int) int {
    N := len(grid)
    M := len(grid[0])
    printGrid(grid)
    //内部从右往左,外部从下往上
    dpToRight := make([][]int, N)
    for i := 0; i < N; i++ {
        dpToRight[i] = make([]int, M)
    }
    for i := N - 1; i >= 0; i-- {
        temp := 0
        for j := M - 1; j >= 0; j-- {
            if grid[i][j] == 0 {
                temp = 0
            } else {
                temp++
            }
            dpToRight[i][j] = temp
        }
    }
    printGrid(dpToRight)
    //内部从右往左,外部从下往上
    dpToDown := make([][]int, N)
    for i := 0; i < N; i++ {
        dpToDown[i] = make([]int, M)
    }
    for j := M - 1; j >= 0; j-- {
        temp := 0
        for i := N - 1; i >= 0; i-- {
            if grid[i][j] == 0 {
                temp = 0
            } else {
                temp++
            }
            dpToDown[i][j] = temp
        }
    }
    printGrid(dpToDown)

    ans := 0
    //左上位置,朝右下看
    for i := 0; i < N; i++ {
        for j := 0; j < M; j++ {
            //dp[i][j]是左上点
            //获取最小值
            edge := getMin(dpToRight[i][j], dpToDown[i][j]) //左上点求小边
            //右上点 左下点
            if edge > 0 &&
                dpToDown[i][j+edge-1] >= edge && //右上点朝下看
                dpToRight[i+edge-1][j] >= edge { //左下点朝右看

                ans = getMax(ans, edge)
            }
        }
    }

    return ans
}

func largest1BorderedSquare22(grid [][]int, ans int) int {
    N := len(grid)
    M := len(grid[0])
    printGrid(grid)
    //内部从右往左,外部从下往上
    dpToRight := make([][]int, N)
    for i := 0; i < N; i++ {
        dpToRight[i] = make([]int, M)
    }
    for i := N - 1; i >= 0; i-- {
        temp := 0
        for j := M - 1; j >= 0; j-- {
            if grid[i][j] == 0 {
                temp = 0
            } else {
                temp++
            }
            dpToRight[i][j] = temp
        }
    }
    printGrid(dpToRight)
    //内部从右往左,外部从下往上
    dpToDown := make([][]int, N)
    for i := 0; i < N; i++ {
        dpToDown[i] = make([]int, M)
    }
    for j := M - 1; j >= 0; j-- {
        temp := 0
        for i := N - 1; i >= 0; i-- {
            if grid[i][j] == 0 {
                temp = 0
            } else {
                temp++
            }
            dpToDown[i][j] = temp
        }
    }
    printGrid(dpToDown)

    //左上位置,朝右下看
    for i := 0; i < N; i++ {
        for j := 0; j < M; j++ {
            //dp[i][j]是左上点
            //获取最小值
            edge := getMin(dpToRight[i][j], dpToDown[i][j]) //左上点求小边
            //右上点 左下点
            for k := edge - 1; k >= ans+1; k-- {
                if dpToDown[i][j+k-1] >= k && //右上点朝下看
                    dpToRight[i+k-1][j] >= k { //左下点朝右看
                    ans = getMax(ans, k)
                    break
                }
            }
        }
    }

    return ans
}

func getMax(a int, b int) int {
    if a > b {
        return a
    } else {
        return b
    }
}

func getMin(a int, b int) int {
    if a < b {
        return a
    } else {
        return b
    }
}

func largest1BorderedSquare2(grid [][]int) int {
    N := len(grid)
    M := len(grid[0])
    printGrid(grid)
    //内部从右往左,外部从下往上
    dpToRight := make([][]int, N)
    for i := 0; i < N; i++ {
        dpToRight[i] = make([]int, M)
    }
    for i := N - 1; i >= 0; i-- {
        temp := 0
        for j := M - 1; j >= 0; j-- {
            if grid[i][j] == 0 {
                temp = 0
            } else {
                temp++
            }
            dpToRight[i][j] = temp
        }
    }
    printGrid(dpToRight)
    //内部从右往左,外部从下往上
    dpToDown := make([][]int, N)
    for i := 0; i < N; i++ {
        dpToDown[i] = make([]int, M)
    }
    for j := M - 1; j >= 0; j-- {
        temp := 0
        for i := N - 1; i >= 0; i-- {
            if grid[i][j] == 0 {
                temp = 0
            } else {
                temp++
            }
            dpToDown[i][j] = temp
        }
    }
    printGrid(dpToDown)

    ans := 0
    //左上位置,朝右下看
    for i := 0; i < N; i++ {
        for j := 0; j < M; j++ {
            //dp[i][j]是左上点
            //获取最小值
            edge := getMin(dpToRight[i][j], dpToDown[i][j]) //左上点求小边
            //右上点 左下点
            for k := edge; k >= ans+1; k-- {
                if dpToDown[i][j+k-1] >= k && //右上点朝下看
                    dpToRight[i+k-1][j] >= k { //左下点朝右看
                    ans = getMax(k, ans)
                    break
                }
            }
        }
    }

    fmt.Println(ans * ans)
    return ans
}

执行结果如下:
图片


左神java代码

以上是关于2021-06-26:给定一个只有0和1组成的二维数组,返回边框全是1的最大正方形面积。的主要内容,如果未能解决你的问题,请参考以下文章

2023-01-14:给定一个二维数组map,代表一个餐厅,其中只有01两种值 map[i][j] == 0 表示(i,j)位置是空座 map[i][j] == 1 表示(i,j)位置坐了人 根据防

2021-08-02:按公因数计算最大组件大小。给定一个由不同正整数的组成的非空数组 A,考虑下面的图:有 A.length 个节点,按从 A[0] 到 A[A.length - 1] 标记;只有当(

2023-03-11:给定一个N*M的二维矩阵,只由字符‘O‘‘X‘‘S‘‘E‘组成, ‘O‘表示这个地方是可通行的平地, ‘X‘表示这个地方是不可通行的障碍, ‘S‘表示这个地方有一个士兵,全

给定 0 和 1 的二维数组,使用回溯找到其中的所有正方形

474-一和零(二维费用的背包问题)

如何创建一个 1 形成“菱形”形状的二维二进制数组