• 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;
        }
    
  • 相关阅读:
    1001.A+B Format(20)
    大一下学期的自我目标
    re模块3
    re模块2
    re模块
    configParser模块
    logging模块
    hashlib模块
    sys模块
    isinstance函数
  • 原文地址:https://www.cnblogs.com/yh-simon/p/12852434.html
Copyright © 2020-2023  润新知