美团研发岗笔试真题练习(编程题4)——最大矩形

题目描述

给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。

输入描述:
输入一个仅包含’0’和’1’的二维字符数组。
第一行输入左大括号{,最后一行输入右大扩号}。
中间每行输入只包含’0’和’1’的字符数组*(字符数组的长度不超过20),字符使用单引号’’,字符之间使用逗号,隔开,字符数组的开始和结束使用大括号{}。
字符数组之间换行,并使用逗号,隔开。
(字符数组的个数不超过20)*。
输出描述:
输出包含字符’1’的最大矩形的面积。

示例1
输入
{
{‘1’,‘0’},
{‘1’,‘0’}
}
输出
2
示例2
输入
{
{‘0’,‘0’},
{‘0’,‘1’}
}
输出
1

分析:
输入呢,就是一个二维的数组s[m][n],m<=20,n<=20,。
现在就是要求出一个矩形面积,面积 r = 长*宽;
长 = 行中包含有字符’1’的位置的下标(最大下标-最小下标)值;
宽 = 列中包含有字符’1’位置的下标(最大-最小)值;

注意是只包含字符’1’的矩形面积,所以重新思考:
使用动态规划,我们可以在线性时间内用上一行每个点的 height,left,和 right 计算出下一行每个点的的height,left,和 right 。

伪代码:


//特殊处理

//处理1
int maxArea(数组)
{
	遍历数组行:
		碰到字符'1',就开始记录行值,直到碰见‘0’停止记录:
			遍历数组列(行值为之前记录的行值):
				碰到字符'0'就开始记录,直到碰见‘0’停止记录:
					计算c*h的面积;
	return c*h;
}
定义主函:
	定义数组s[20][20];
	分配动态空间;
	输入数组:输入这里就比较特殊了,不安常规套路来,有一个固定的形式,所以要进行判断。
//处理2


代码:

  1. case通过率为16.67%
#include
using namespace std;

int maxArea(char** s, int K, int n)
{
	//特殊处理
	//处理
	int count1=0,count2=0;
	int max=0;
	for(int j=0;j<n;j++)
	{
		for(int i=0;i<K;i++)
		{
			if(s[i][j] == '1')
			{
				++count1;
				for(int x=0;x<count1;x++)
				{
					for(int y=0;y<n;y++)
					{
						if(s[x][y] == '1')
						{
							++count2;
						}
						else
						{
							break;
						}
					}
				}
			}
			
			int r = count1*count2;		
			if(r > max)
				max = r;
			break;
		}
	}
	return max;
}

int main()
{
	char **s;

	s =(char**)malloc(sizeof(char*)*20);
	for(int i=0;i<20;i++)
	{
		s[i] = (char*)malloc(sizeof(char)*20);
	}
	
	for(int i=0;i<20;i++)
	{
		for(int j=0;j<20;j++)
		{
			s[i][j] = '0';
		}
	}
	//对于输入比较特殊了
    int i=-2, j=0, k=0;
    int K=-1;int n;
	char ch;
    while(cin.get(ch))
    {
        if(ch=='{')
        {
            i++;//记录每行的值
            j=0;//记录每列的值
            k++;//判断是否输入完成,标志位两个大花括号{{}}
            K++;//K为最终行值
        }
        if(ch=='}')
        {
            n=j;//n为最终列值
            k--;
        }
        if(ch=='1')
        {
            s[i][j]='1';
            j++;
            
        }
        if(ch=='0')
        {
            s[i][j]='0';
            j++;
           
        }
        
        if(k==0)//输入完成,跳出
			break;
    }

	int max = maxArea(s, K, n);
	cout<<max<<endl;

	
	for(int i=0;i<20;i++)
	{
		free(s[i]);
	}
	free(s);

	return 0;
}
  1. 升级后的代码通过率为100%
    这个在提交测试平台是提示: fatal error: 'windows.h' file not found,所以我给注释掉了,然后就通过编译了,但在VS下编译仍需加上这个头文件,可能是OJ后台自动包含了这个库的内容了吧。
#include
#include 
#include 
using namespace std;

/*
 * 动态规划
 * 时间复杂度O(mn) 空间复杂度O(n)
 * m,n为数组行列数
 */
int maxRectangleArea(char** s, int K, int n) 
{
	int rows = K, cols = n;
    if(K==0 || n==0) 
		return 0;
    vector<int> left(cols, 0);      // 最左边的1位置 左边界
    vector<int> right(cols, cols);  // 右边界
    vector<int> height(cols, 0);
    int maxArea = 0;
    for (int i = 0; i < rows; ++i) 
	{
        int curLeft = 0;            // 遇到的最右边的0的序号加1
        int curRight = cols;        // 遇到的最左边的0的序号
        for (int j = 0; j < cols; ++j) 
		{
            if(s[i][j] == '1')
                height[j] += 1;
            else
                height[j] = 0;
        }
        // 更新left
        for (int j = 0; j < cols; ++j) 
		{
            if (s[i][j] == '1')
                left[j] = max(left[j],curLeft);
            else{
                left[j] = 0;
                curLeft = j+ 1;
            }
        }
        // 更新right
        for (int j = cols-1; j >=0 ; --j) {
            if (s[i][j] == '1')
                right[j] = min(right[j],curRight);
            else{
                right[j] = cols;
                curRight = j;
            }
        }
        // 更新最大面积
        for (int j = 0; j < cols; ++j) {
            maxArea = max(maxArea, height[j] * (right[j] - left[j]));
        }
    }
    return maxArea;
}


int main()
{
	char **s;

	s =(char**)malloc(sizeof(char*)*20);
	for(int i=0;i<20;i++)
	{
		s[i] = (char*)malloc(sizeof(char)*20);
	}
	
	for(int i=0;i<20;i++)
	{
		for(int j=0;j<20;j++)
		{
			s[i][j] = '0';
		}
	}

	//对于输入比较特殊了
    int i=-2, j=0, k=0;
    int K=-1;int n;
	char ch;
    while(cin.get(ch))
    {
        if(ch=='{')
        {
            i++;//记录每行的值
            j=0;//记录每列的值
            k++;//判断是否输入完成,标志位两个大花括号{{}}
            K++;//K为最终行值
        }
        if(ch=='}')
        {
            n=j;//n为最终列值
            k--;
        }
        if(ch=='1')
        {
            s[i][j]='1';
            j++;
            
        }
        if(ch=='0')
        {
            s[i][j]='0';
            j++;
           
        }
        
        if(k==0)//输入完成,跳出
			break;
    }

	int maxArea = maxRectangleArea(s, K, n);
	cout<<maxArea<<endl;

	
	for(int i=0;i<20;i++)
	{
		free(s[i]);
	}
	free(s);

	return 0;
}

笔记:

  • 这个题的特殊点就在输入部分,所以没有用纯C++里的vector来进行定义。

  • 为二维数组开辟空间:

char **s;

s =(char**)malloc(sizeof(char*)*20);
for(int i=0;i<20;i++)
{
	s[i] = (char*)malloc(sizeof(char)*20);
}

释放二位数组的动态空间:注意顺序不能乱,先释放数组内空间,再释放指针空间!!

for(int i=0;i<20;i++)
{
	free(s[i]);
}
free(s);
  • C++中vector的定义方式
#include
#include
using namespace std;
int main()
{
    //第一种定义方式:定义未知长度的向量
    vector<int> vec;
    
    //第二种定义方法,把n个长度的数初始化为0
    vector<int> vec(n,0);
    
    //第三种定义方法,是定义一个固定长度的数组
    vector<int> vec(100);
    
    //第四种是定义一个二维数组,但是需要手动初始化才能够使用
    vector<int> vec[1005];
    
    //第五种也是二维数组的定义方式,是在定义的时候就把数据初始化了
    vector<vector<int> > vec(n,vector<int>(n,0));

    return 0;
}

你可能感兴趣的:(笔试题,数据结构,java,算法,动态规划,leetcode)