全部由1组成的子矩形的数量

题目描述:

给定一个二维数组matrix,其中的值不是0就是1,返回全部由1组成的子矩阵的数量。

way:

假设我们遍历矩形的每一行,以当前遍历到的行作为地基,去看这一行的直方图(直方图介绍 ->直方图的最大长方形面积-CSDN博客)中全部由1组成的子矩阵的个数,将每一行得到的子矩阵数加起来,得到答案,将二维问题转变为了一维问题,所以就是像下面这样。

第一行:1 1 1 1  0 1

第二行:2 2 2 2  0 2 

第三行:3 3 3 3  1 3

第四行:   0 4 4 4  2 4 (做地基时如果有0直接为0,地基都没有,上面的没法垒起来的)

第五行:1 5 0 5  3 5

为了明显点,假设这5行中的有一行是 3, 2, 4, 2, 5,那么计算这一行的直方图的子矩阵的数量就是,以当前行的每个元素作为所在子矩阵中的最小高度,得到一块区域,假设以第4个2作为最低高度,那么可以得到如下的一块区域,在这个区域中,对于高度为2的子矩阵的数量,有1-1列,1-2列,1-3列,1-4列,1-5列,2-2列,2-3,2-4,2-5,3-3,3-4,3-5,4-4,4-5,5-5 这(1+5)*5/2=15个,对于高度为1的数量,也有15个,所以如果区域长度为L,高度为h,那么子矩阵的数量就是  L * (L+1)/2 * h 个,对于上面说的,有 5 *(5+1)/2 *2 = 30个,这个高度h为当前选的最低高度 - max(left, right) (left,right 分别为它的左右两边离它最近且比它 小于or等于 的数,就像第一个2,左边比它小的数没有,右边比它 等于 的数是第2个2,然后h=2-2=0, 没有计算以第一个2为最小高度时的子矩阵数,到了第2个2的时候,左边比它小的数没有,右边比它小的数也没有,h=2-0=2, 到了第2个2的时候才计算了下面的阴影部分的子矩阵的数量,这样就不会算重复,只会在最后一个2的时候去计算以2为最低高度的时候那块高度为2连通的大区域的子矩阵数,必须是 小于等于,必须是 h = 高度差,这样就不会在 最低高度 =3 的时候去计算高度为2的子矩阵数,那样高度为2的区域其实还没有完全连起来形成一块大区域,会算重)。注意要一行一行的做地基 (地基必被算)得到一个个直方图数组去算去加和,其实你按我上面的说法1-1,1-2,1-3....,不同高度这样一行一行的去算就知道对不对了。

#include<iostream>
#include<vector>
#include<stack>
using namespace std;


int subMatrixCount(vector<int> height)
{
	int N = height.size();
	stack<int>st;
	int num = 0;
	for (int i = 0; i < N; i++)
	{
		while (!st.empty() && height[i] <= height[st.top()])
		{
			int topIndex = st.top();
			st.pop();
			int leftIndex = st.empty() ? -1 : st.top();
			int rightIndex = i;
			//(rightIndex-1)-(leftIndex+1) + 1
			int L = rightIndex - 1 - leftIndex;
			int h = height[topIndex] - max(height[rightIndex], leftIndex >= 0 ? height[leftIndex] : 0);
			num += L * (L + 1) / 2 * h;
		}
		st.push(i);
	}
	while (!st.empty())
	{
		int topIndex = st.top();
		st.pop();
		int leftIndex = st.empty() ? -1 : st.top();
		int rightIndex = N;
		//(rightIndex-1)-(leftIndex+1) + 1
		int L = rightIndex - 1 - leftIndex;
		int h = height[topIndex] - max(0, leftIndex >= 0 ? height[leftIndex] : 0);
		num += L * (L + 1) / 2 * h;
	}
	return num;
}


int allSubMatrixCountBy1(vector<vector<char>> mp)
{
	if (mp.size() == 0) return 0;
	int M = mp.size();
	int N = mp[0].size();
	vector<int>row(N);
	int sum = 0;
	for (int i = 0; i < M; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (mp[i][j] == '1')
			{
				row[j] += 1;
			}
			else
			{
				row[j] = 0;
			}
		}
		sum += subMatrixCount(row);
	}
	return sum;
}


int main()
{
	vector<vector<char>> mp = {
		{'1', '1'},
		{'1', '1'}
	};
	int sum = allSubMatrixCountBy1(mp);
	cout << sum << endl;  //9
	return 0;
}

 

相关推荐

  1. 1277. 统计全为 1 正方形矩阵

    2024-07-21 19:46:02       53 阅读
  2. Vue中嵌套路使用

    2024-07-21 19:46:02       30 阅读
  3. 796. 矩阵

    2024-07-21 19:46:02       52 阅读
  4. 云存储架构是什么组成

    2024-07-21 19:46:02       32 阅读
  5. 15 动态规划解统计全为1正方形矩阵

    2024-07-21 19:46:02       49 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 19:46:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 19:46:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 19:46:02       45 阅读
  4. Python语言-面向对象

    2024-07-21 19:46:02       55 阅读

热门阅读

  1. [强化学习马里奥 MarioRL]-- 环境ENV 3

    2024-07-21 19:46:02       17 阅读
  2. ubuntu 上安装中文输入法

    2024-07-21 19:46:02       17 阅读
  3. 记一次通过udev自动加在i2c接口触摸驱动过程

    2024-07-21 19:46:02       16 阅读
  4. 优选算法之滑动窗口(下)

    2024-07-21 19:46:02       18 阅读
  5. Linux常用命令(备忘自查)

    2024-07-21 19:46:02       15 阅读
  6. 计算机视觉发展历程

    2024-07-21 19:46:02       17 阅读
  7. python中的fire和Linux shell中的参数传递

    2024-07-21 19:46:02       14 阅读
  8. Vue.js 首屏加载优化:实战与策略

    2024-07-21 19:46:02       13 阅读