1277.统计全为1的正方形子矩形

image-20200508173255960

动态规划

思路

  • 用dp(i,j)=x既可以表示以(i,j)为右下角的正方形的数目(即边长为1,2..,x的正方形各一个),也可以表示以(i,j)为右下角的正方形的最大边长。

  • 计算出所有dp(i,j)的值并进行累加,即为所求。

  • dp(i,j)与相邻位置的关系,参考官方讲解

    image-20200508173952913

    image-20200508174014201

代码

 /**
     * 7ms  动态规划
     * @param matrix
     * @return
     */
    public int countSquares(int[][] matrix) {
        int ans = 0;
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return 0;
        int r = matrix.length, c = matrix[0].length;
        int[][] dp = new int[r][c];
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                if (matrix[i][j] == 1) {
                    //边界处理  i==0或者j==0
                    if (i == 0 || j == 0) {
                        dp[i][j] = 1;
                        ans++;
                    } else {
                        //递推公式
                        dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
                        ans += dp[i][j];
                    }
                }
            }
        }
        return ans;
    }

暴力解法

思路

  • 从头开始遍历,以(i,j)为正方形的左上角
  • 计算以(i,j)为左上角,且可能构成正方形的最大边长 curMaxSide
  • 在不超过curMaxSide条件下 边长逐步加1 判断是否满足题设要求
    • 先判断对角线上的点 (i+k,j+k), 因为边长每延长1 就多出的 一列 一行 ,而该点即为多出的一行一列的公共点
    • 再判断一行一列各个元素值是否满足题设
  • 若符合 累加 ,否则退出循环 退出嵌套for循环需注意细节:可以引用flag标记退出外层循环

代码

/**
     * 7ms
     * 暴力解法
     */
    public int countSquares2(int[][] matrix){
        int ans=0;
        if(matrix==null||matrix.length==0||matrix[0].length==0) return  ans;
        int r=matrix.length,c=matrix[0].length;
        for(int i=0;i<r;i++){
            for(int j=0;j<c;j++){
                if(matrix[i][j]==1){
                    ans++;
                    //以(i,j)为左上角 能构成最大正方形的长度
                    int curMaxSide=Math.min(r-i, c-j);
                    for(int k=1;k<curMaxSide;k++){
                        boolean flag=true;
                        //先判断对角线  该点其实是多出的 一行 一列的公共点 
                        if(matrix[i+k][j+k]==0){
                            break;
                        }
                        //边长增加1 判断多出来的一行 一列 的元素值 是否为 1 
                        for(int m=0;m<k;m++){
                            if(matrix[i+k][j+m]==0||matrix[i+m][j+k]==0){
                                flag=false;
                                break;
                            }
                        }
                        if(flag){
                            ans++;
                        }else{
                            break;
                        }
                    }
                }
            }
        }
        return ans;
    }
posted @ 2020-05-08 18:46  YH_Simon  阅读(463)  评论(0编辑  收藏  举报