zoukankan      html  css  js  c++  java
  • 最大矩形, 统计全1子矩阵

    美团笔试题-最大矩形

    暴力直接解决, 输入处理较为麻烦。
    LeetCode 85 一样。

    import java.util.*;
    public class Main {
        static int solve(int[][] arr, int n, int m) {
            int area = 0;
            for(int a = 0; a < n; a++){
                for(int b = 0; b < m; b++) {
                    for(int c = 0; c <= a; c++){
                        for(int d = 0; d <= b; d++) {
                            int t = 0;
                            for(int i=c; i <= a; i++)
                                for(int j=d; j <= b; j++)
                                    if(arr[i][j] == 1) t++;
                            if(t == (a-c+1)*(b-d+1))
                                area = Math.max(area, t);
                        }
                    }
                }
            }
            return area;
        }
        public static void main(String[] args){
            Scanner sc = new Scanner(System.in);
            if(sc.hasNext()) sc.nextLine();
            List<String> list = new ArrayList<>();
            while(true){
                char[] s = sc.nextLine().toCharArray();
                StringBuilder sb = new StringBuilder();
                for(int i=0; i < s.length;i++)
                    if(s[i] == '0' || s[i] == '1')
                        sb.append(s[i]);
                if(sb.length() == 0) break;
                list.add(sb.toString());
                if(s[s.length-1] != ',') break;
            }
            if(sc.hasNext()) sc.nextLine();
            int n = list.size(), m = list.get(0).length();
            int[][] a = new int[n][m];
            for(int i=0; i < n; i++)
                for(int j=0; j < m; j++)
                    a[i][j] = list.get(i).charAt(j) == '1' ? 1 : 0;
            int area = solve(a, n, m);
     
            System.out.println(area);
        }
    }
    
    

    Leetcode 1504. 统计全1子矩阵

    N, M <= 150
    使用二维前缀和优化,时间复杂度:O(N*M*N*M)

    class Solution {
        public int numSubmat(int[][] mat) {
            int n = mat.length, m = mat[0].length;
            int[][] f = new int[n+1][m+1];
            for(int i=1; i <= n; i++)
                for(int j=1; j <= m; j++) {
                    f[i][j] = f[i-1][j]+f[i][j-1]-f[i-1][j-1];
                    if(mat[i-1][j-1] == 1) f[i][j]++;
                }
            int count = 0;
            for(int a = 1; a <= n; a++) {
                for(int b=1; b <= m; b++) {
                    for(int c=1; c <= a; c++) {
                        for(int d=1; d <= b; d++) {
                            int t = f[a][b] - f[a][d-1] - f[c-1][b] + f[c-1][d-1];
                            if(t == (a-c+1)*(b-d+1))
                                count++;
                        }
                    }
                }
            }
            return count;
        }
    }
    

    优化版思路:

    1. 求出每行的前缀和
    2. 遍历所有可能子矩阵的左列和右列, 根据前缀和和以计算出每一行左列到右列间1的数量。
    3. 遍历行, 连续x行每行左列到右列间全为1,则有 x(x+1)/2 种矩阵。
      时间复杂度:O(N*M*M)
    class Solution {
        public int numSubmat(int[][] mat) {
            int n = mat.length, m = mat[0].length;
            int[][] f = new int[n][m+1]; //每行的前缀和
            for(int i=0; i < n; i++) {
                for(int j=1; j <= m; j++)
                    f[i][j] = f[i][j-1] + mat[i][j-1];
            }
            int count = 0;
            for(int a = 0; a < m; a++) { // 矩阵左列
                for(int b=a; b < m; b++) { // 矩阵右列
                    int cnt = 0;
                    for(int i=0; i < n; i++) {
                        int sum = f[i][b+1] - f[i][a];
                        if(sum == b-a+1)
                            cnt++;
                        else {
                            count += cnt*(cnt+1) / 2;
                            cnt = 0;
                        }
                    }
                    if(cnt != 0) count += cnt*(cnt+1) / 2;
                }
            }
            return count;
        }
    }
    
  • 相关阅读:
    记忆碎片:我的2007
    查看 Oracle 是用spfile 启动还是 pfile 启动
    Oracle 10g OCP 042 题库 71120 题 共168题
    Oracle OLAP 与 OLTP 介绍
    Oracle Data Guard Switchover 切换
    Linux 终端访问 FTP 及 上传下载 文件
    多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP
    Oracle 表连接方式(内连接/外连接/自连接) 详解
    Oracle 表连接方式(内连接/外连接/自连接) 详解
    查看 Oracle 是用spfile 启动还是 pfile 启动
  • 原文地址:https://www.cnblogs.com/lixyuan/p/13288574.html
Copyright © 2011-2022 走看看