数组元素与X轴组成容器的容积

问题一


问题描述:

假设一个数组A[n]的n个元素都是非负整数的,(i,A[i])(0<=i<n)表示在X轴上i位置有高为A[i]的“墙”(假设墙的厚度为0),求n堵“墙”中任意两堵“墙”和X轴组成的容器的最大容水量。

例如,int A[] = {2,4,3};则任意两堵“墙”与X轴可以组成的最大容水量为:4

                                

算法思想

由数组的两头向中间遍历,忽略比当前容器较矮的“墙”还要矮的墙。时间复杂度O(n),空间复杂度O(1).

实现


	/**
		最大容水量:
			墙没有宽度,求任意两堵墙和X轴组成的容器的最大值。
	*/
    int maxArea(vector<int> &height) {
		int bidx,eidx,maxarea;
		bidx = 0;
		eidx = height.size()-1;
		maxarea = 0;
		while(bidx<eidx){
			if(height[bidx]>=height[eidx]){
				maxarea = max(maxarea,height[eidx]*(eidx - bidx));
				eidx--;
			}else{
				maxarea = max(maxarea,height[bidx]*(eidx - bidx));
				bidx++;
			}
		}
		return maxarea;
    }



问题二


问题描述

和问题一类似,数组元素的大小是非负数,代表墙的高度,墙的厚度为0。不过不是要求最大的容水量,而是要求总的容水量。
例如,int A[] = {2,4,3};则总的容水量为:5
                   

算法思想

和问题一的思想类似,也是有由数组两边向中间遍历,忽略比当前容器较矮“墙”还要矮的墙,将可以确定容量的部分的容量累加到总的容量上。时间复杂度为O(n),空间复杂度为O(1)

实现



	/**
		总容水量:
			墙没有宽度,求总的容水量
	*/
	int sumArea(vector<int> &height){
		int bidx,eidx,pidx,sum;
		bidx = 0 ;
		eidx = height.size()-1;
		sum = 0;
		while(bidx<eidx){
			if(height[bidx]>=height[eidx]){
				pidx = eidx - 1;
				while(pidx>bidx && height[pidx]<height[eidx]){
					pidx--;
				}
				sum += min(height[eidx],height[pidx])*(eidx - pidx);
				eidx = pidx;
			}else {
				pidx = bidx + 1;
				while(pidx<eidx && height[pidx]<height[bidx]){
					pidx++;
				}
				sum += min(height[bidx],height[pidx])*(pidx - bidx);
				bidx = pidx;
			}
		}
		return sum;
	}


问题三


问题描述

同样是非负数组A[n],元素值代表墙的高度,但墙的厚度为1,且墙是依次挨着的,求总的容水量。
例如,int A[] = {2,4,3};  则总的容水量为:0

又如:
            int A[] = {4,2,3,4};则总的水容量为:3

                                                   

算法思想

和问题二的思想类似,不过在遍历的过程中需要记录要减去的总容量(既被忽略墙的高度和),如果上面第二个图最终的结果实际上是8-(2+3) = 3。时间复杂度为O(n),空间复杂度为O(1).

实现

	/*
		总容水量:
			墙的宽度为1,求总的总容水量
	*/
	int sumAreaW1(vector<int> &height){
	
		if(height.size()<=2){//少于三堵墙 都不可能存水
			return 0;
		}

		int bidx,eidx,sum,pidx;
		bidx = 0;
		eidx = height.size()-1;
		sum = 0;
		int tmpsum = 0;
		while(height[bidx+1]>=height[bidx] && bidx+1<height.size()){
			bidx++;
		}
		while (height[eidx-1]>=height[eidx] && eidx-1>=0){
			eidx--;
		}
		while(bidx<eidx-1){
			if(height[bidx]>=height[eidx]){
			
				pidx = eidx - 2;
				tmpsum += height[eidx-1];
				while(pidx>bidx && height[pidx]<height[eidx]){
					
					tmpsum += height[pidx];
					pidx--;
				}
				sum +=  min(height[eidx],height[pidx])*(eidx - pidx -1) - tmpsum;
				eidx = pidx;
				tmpsum = 0;
			}else{
			
				pidx = bidx + 2;
				tmpsum += height[bidx+1];
				while(pidx<eidx && height[pidx]<height[bidx]){
					
					tmpsum += height[pidx];
					pidx++;
				}
				sum += min(height[bidx],height[pidx])*(pidx - bidx - 1) - tmpsum;
				bidx = pidx;
				tmpsum = 0;
			}
		}
		return sum;
	}
};

测试程序和测试结果


测试程序

int main(){
	Solution sln;
	int A0[] = {2,4,3,5,7};
	vector<int> height0(A0,A0+5);
	cout<<"maxArea:"<<sln.maxArea(height0)<<endl;
	cout<<"sumArea:"<<sln.sumArea(height0)<<endl;
	cout<<"sumAreaW1:"<<sln.sumAreaW1(height0)<<endl;
	cout<<"-------------"<<endl;

	int A2[] = {2,4,3};
	vector<int> height2(A2,A2+3);
	cout<<"maxArea:"<<sln.maxArea(height2)<<endl;
	cout<<"sumArea:"<<sln.sumArea(height2)<<endl;
	cout<<"sumAreaW1:"<<sln.sumAreaW1(height2)<<endl;
	cout<<"-------------"<<endl;

	int A3[] = {2,4,3,7};
	vector<int> height3(A3,A3+4);
	cout<<"maxArea:"<<sln.maxArea(height3)<<endl;
	cout<<"sumArea:"<<sln.sumArea(height3)<<endl;
	cout<<"sumAreaW1:"<<sln.sumAreaW1(height3)<<endl;
	cout<<"-------------"<<endl;

	int A4[] = {5,4,3,7,9,2};
	vector<int> height4(A4,A4+6);
	cout<<"maxArea:"<<sln.maxArea(height4)<<endl;
	cout<<"sumArea:"<<sln.sumArea(height4)<<endl;
	cout<<"sumAreaW1:"<<sln.sumAreaW1(height4)<<endl;
	cout<<"-------------"<<endl;

	int A5[] = {5,4,5};
	vector<int> height5(A5,A5+3);
	cout<<"maxArea:"<<sln.maxArea(height5)<<endl;
	cout<<"sumArea:"<<sln.sumArea(height5)<<endl;
	cout<<"sumAreaW1:"<<sln.sumAreaW1(height5)<<endl;
	cout<<"-------------"<<endl;

	int A6[] = {5};
	vector<int> height6(A6,A6+1);
	cout<<"maxArea:"<<sln.maxArea(height6)<<endl;
	cout<<"sumArea:"<<sln.sumArea(height6)<<endl;
	cout<<"sumAreaW1:"<<sln.sumAreaW1(height6)<<endl;
	cout<<"-------------"<<endl;

	int A7[] = {5};
	vector<int> height7(A7,A7+0);
	cout<<"maxArea:"<<sln.maxArea(height7)<<endl;
	cout<<"sumArea:"<<sln.sumArea(height7)<<endl;
	cout<<"sumAreaW1:"<<sln.sumAreaW1(height7)<<endl;
	cout<<"-------------"<<endl;

	int c;
	cin>>c;
}

测试结果


总结


上面三个问题的解法是类似的,要做到时间复杂度为O(n),空间复杂度为O(1),关键思路是由数组两边向中间遍历,忽略一些该忽略的容器。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值