使用线段数,先枚举一条边作为较小的一条边,再找左边比它大和最右边比它大的边,两者的较大值就是以这条边为较短边的最大面积,构建和查询线段数的时间是log(n),总的时间是nlog(n)
class Solution {
struct segTree{
int l,r;
int v;
segTree* left,*right;
segTree(int val):v(val),left(NULL),right(NULL){};
};
public:
void build(segTree* &root,vector<int> &nums,int l,int r)
{
if(r==l)
{
root=new segTree(l);
root->l=l;
root->r=r;
return;
}
int mid=(l+r)>>1;
root=new segTree(0);
build(root->left,nums,l,mid);
build(root->right,nums,mid+1,r);
if(nums[root->left->v]>nums[root->right->v])
root->v=root->left->v;
else
root->v=root->right->v;
root->l=l;
root->r=r;
}
int search(segTree* &root,vector<int>& nums,int l,int r)
{
if(root==NULL||root->l>r||root->r<l)
return -1;
if(root->l==l&&root->r==r)
return root->v;
int mid=(root->l+root->r)>>1;
if(r<=mid)
return search(root->left,nums,l,r);
if(l>=mid+1)
return search(root->right,nums,l,r);
int vl=search(root->left,nums,l,mid);
int vr=search(root->right,nums,mid+1,r);
if(nums[vl]>nums[vr])
return vl;
return vr;
}
int binarySearchR(segTree* &root,vector<int>& nums,int d,int l,int r)
{
int pos=l;
int ans=pos;
while(l<=r)
{
pos=search(root,nums,l,r);
if(nums[pos]>=d)
{
ans=pos;
}
else
return ans;
l=pos+1;
}
return ans;
}
int binarySearchL(segTree* &root,vector<int>& nums,int d,int l,int r)
{
int pos=r;
int ans=pos;
while(l<=r)
{
pos=search(root,nums,l,r);
if(nums[pos]>=d)
{
ans=pos;
}
else
return ans;
r=pos-1;
}
return ans;
}
int maxArea(vector<int>& height) {
int n=height.size();
int i,j;
int curArea,ans=0;
segTree* root;
build(root,height,0,n-1);
for(i=0;i<n;i++)
{
if(height[i]==0)
continue;
int l=binarySearchL(root,height,height[i],0,i);
int r=binarySearchR(root,height,height[i],i,n-1);
curArea=max((i-l),(r-i))*height[i];
ans=max(ans,curArea);
}
return ans;
}
};
/*
[1,2,1,5,6,8,9,22,1,,3,5,6,7,4,6,8,10,2,0,3,5,7,8,5,12,4,10]
*/
另一种简单的思想,two points 向中间逼近
class Solution {
public:
int maxArea(vector<int>& height) {
int n=height.size();
int i,j;
int curArea,ans=0;
int left=0,right=n-1;
while(left<right)
{
curArea=min(height[right],height[left])*(right-left);
ans=max(curArea,ans);
if(height[left]>height[right])
right--;
else
left++;
}
return ans;
}
};
还有一种方法,先将数组排序,纪录下标最大和最小的点,是一种贪心策略;
class Solution {
public:
struct Node{
int h;
int ind;;
};
static bool cmp(Node &a,Node &b)
{
return a.h>b.h;
}
int maxArea(vector<int>& height) {
int n=height.size();
int i,j;
int curArea,ans=0;
Node H[n];
for(i=0;i<n;i++)
{
H[i].h=height[i];
H[i].ind=i;
}
std::sort(H,H+n,cmp);
int Max=H[0].ind,Min=H[0].ind;
for(i=0;i<n;i++)
{
curArea=max((Max-H[i].ind),(H[i].ind-Min))*H[i].h;
ans=max(ans,curArea);
if(H[i].ind<Min)
Min=H[i].ind;
if(H[i].ind>Max)
Max=H[i].ind;
}
return ans;
}
};