2014腾讯实习生招聘数组墙算法

题目:随机给定一个整型数组,每个数组中的数字代表数组所在位置墙的高度,问这个数组所能拼凑的最大矩形墙的面积为多少。

例如,如下图示,数组{2, 1, 6, 5, 4, 7, 2}所能拼凑出的最大矩形为{6, 5, 4, 7}上所组成的高度为4的墙(浅蓝色部分),其面积为4*4 = 16.



算法分析:首先把最初的数组source备份到backup数组中,另外新建maxnum数组,存储每个元素所在的最大的矩形的面积值,初始值置0。从backup数组开始,找出整个数组中最小的元素,backup数组中所有的元素都减去这个元素,将数组按0元素进行切割成子的新数组,计算数组的长度与新生成矩形的高度,求出新的最大矩形面积值并与maxnum中存储的数值进行比较,如果大则更新。算法复杂度为O(n).

具体如下:

1.备份source到backup,新建maxnum并置0。

2.按0元素切割数组,如果能得到有效子数组,将子数组中的最小元素求出,更新backup数组与maxnum数组。

3.重复2直到按0元素切割不能获得有效子数组。

4.继续处理下一段2中所得到的有效子数组。


流程图如下图示:


以示例图为例,整个流程的数组变换过程如下各图所示:


最后可以在max中得到各个元素所在的最大矩形的面积。

JAVA实现的代码如下:

import java.util.Random;


public class Find_max_Rectangle {


public static void main(String[] args) {
// TODO Auto-generated method stub
int[] source = new int[20];
createRandomA(source);
printA(source);
int[] backup = new int[source.length];
int[] maxnum = new int[source.length];
for(int i = 0; i < source.length; i ++){
backup[i] = source[i];
maxnum[i] = 0;
}
findmax(source, backup, maxnum, new int[]{0, source.length - 1, 0, source.length - 1});
System.out.println();


int max = 0;
for(int i = 0; i < maxnum.length; i ++){
max = max > maxnum[i] ? max : maxnum[i];
System.out.print(maxnum[i] + " ");
}
System.out.println();
System.out.println(max);
}


private static void printA(int[] source) {
// TODO Auto-generated method stub
for(int i = 0; i < source.length; i ++)
System.out.print(source[i] + " ");
}


private static int findmax(int[] source, int[] backup, int[] maxnum, int[] tag) {
// TODO Auto-generated method stub

while(get_cutoff_backup(backup, tag)){

int tmp = backup[tag[2]];

for(int i = tag[2]; i <= tag[3]; i ++) {
tmp = tmp < backup[i] ? tmp : backup[i];
}

for(int i = tag[2]; i <= tag[3]; i ++) backup[i] -= tmp;

if(tag[3] >= tag[2] && maxnum[tag[2]] < (tag[3] - tag[2] + 1) * (source[tag[2]] - backup[tag[2]])){
for(int i = tag[2]; i <= tag[3]; i ++) 
maxnum[i] = (tag[3] - tag[2] + 1) * (source[i] - backup[i]);
findmax(source, backup, maxnum, new int[]{tag[2], tag[3], tag[2], tag[3]});
}

tag[0] = tag[2] + 1;
if(tag[0] > tag[1]) break;
}
return -1;
}


private static boolean get_cutoff_backup(int[] backup, int[] tag) {
// TODO Auto-generated method stub

boolean have_a_sub_head = false;
for(int i = tag[0]; i <= tag[1]; i ++){
if(!have_a_sub_head && backup[i] != 0) {tag[2] = i; have_a_sub_head = true;}
if(have_a_sub_head && backup[i] == 0) {tag[3] = i - 1; return true;}
if(have_a_sub_head && i == tag[1] && backup[i] != 0) {tag[3] = i; return true;}
}
return false;
}


private static void createRandomA(int[] a) {
// TODO Auto-generated method stub
Random random = new Random();
for(int i = 0; i < a.length; i ++)
a[i] = random.nextInt(30);
}


}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值