给定n个非负整数a1,a2,…,an,其中每个数字表示坐标(i, ai)处的一个点。以(i,ai)和(i,0)(i=1,2,3...n)为端点画出n条直线。你可以从中选择两条线与x轴一起构成一个容器,最大的容器能装多少水?
注意:你不能倾斜容器
注意:你不能倾斜容器
例如:
输入 [1,8,6,2,5,4,8,3,7]
输出: 49
输出: 49
class Solution {
public:
int maxArea(vector<int> &height) {
if(height.size()<=1)
return 0;
int st=0,end=height.size()-1,v=0,max_v=0;
while(st<end){
v=(end-st)*(height[st]>height[end]?height[end]:height[st]);
max_v=v>max_v?v:max_v;
if(height[st]>height[end])
end--;
else
st++;
}
return max_v;
}
};
public class Solution {
public int maxArea(int[] height) {
if (height.length<2){
return 0;
}
int left = 0;
int right = height.length-1;
int maxV = 0;
while (left<right){
int v = Math.min(height[left],height[right])*(right-left);
maxV = Math.max(v,maxV);
if (height[left]<height[right]){
left++;
}else {
right--;
}
}
return maxV;
}
}
//貌似简单,仔细一想有点难,但是其实很简单。
//这是逼近算法么?不是把`~~
for(int i = 0,j = height.size()-1;i<j;)
{
MAXI = max(min(height[i],height[j])*(j-i),MAXI);
height[i]>height[j]?j--:i++;
} /**
*
* @author ChopinXBP
* Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai).
* n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
* Note: You may not slant the container and n is at least 2.
* 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。
* 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
* 说明:你不能倾斜容器,且 n的值至少为 2。
*
*/
public class ContainerWithMostWater { public static void main(String[] args) { // TODO Auto-generated method stub int[] height = {1,8,6,2,5,4,8,3,7}; int[] height2 = {1,2,4,3}; System.out.println(maxArea(height)); System.out.println(maxArea(height2)); System.out.println(maxArea2(height)); System.out.println(maxArea2(height2)); } //对每一条线段i,找左右两端距离i最长的不小于i的长度的线段j。j作为长,i作为宽,ij构成的矩形是包含线段i的面积最大的矩形。
public static int maxArea(int[] height) {
int result = 0;
for(int i = 0; i < height.length; i++) {
int num = height[i];
int longest = 0;
int idx = 0;
while(idx < i) {
if(height[idx] >= num) {
longest = i - idx;
break;
}
idx++;
}
idx = height.length - 1;
while(idx > i && idx - i > longest) {
if(height[idx] >= num) {
longest = idx - i;
break;
}
idx--;
}
if(num * longest > result) {
result = num * longest;
}
}
return result;
}
//设置left和right从两端逼近,每次计算其和较短边围成的矩形的面积,之后移动较短边。逼近过程中最大的矩形面积即为所求。
public static int maxArea2(int[] height) {
int result = 0;
int right = height.length - 1;
int left = 0;
while(left < right) {
int shorter = height[right] < height[left] ? height[right] : height[left];
if((right - left) * shorter > result) {
result = (right - left) * shorter;
}
//每次移动较短边(移动较长边可能会导致下一个矩形因为短边限制取不到最优)
if(height[right] < height[left]) {
right--;
}else {
left++;
}
}
return result;
}
}
#include<math.h>
class Solution {
public:
int maxArea(vector<int> &height) {
//Note: You may not slant the container.
//暴力搜索,时间复杂度为O(n^2) (120ms)
/*
int result=0;
int size = height.size();
for(int i=0;i<size;i++){
for(int j=i+1;j<size;j++){
int area = (j-i)*min(height[i],height[j]);
if(area>result)result = area;
}
}
return result;
*/
//方式二:贪心算法策略(10ms)
int result=0;
if(height.size()<=1) return result; //无法构成容器
int i=0,j=height.size()-1;
while(i<j){
int area = (j-i)*min(height[i],height[j]);
if(area>result)result = area;
if(height[i]>height[j]){
j--;
}else{
i++;
}
}
return result;
}
};
//设置left、right两个下标,代表左右两条直线,从两端开始遍历,对于两条直线和X轴所形成的的容器,若左边的直线高度大于右边的直线高度,则右边直线下标right--,反之左边下标直线下标left++。
//因为容器所成盛水的体积等于宽度(right-left)乘以较低的直线高度,淘汰较低的直线高度,尝试寻找更高的直线高度,继而尝试寻找更大的体积。
public class Solution {
public int maxArea(int[] height) {
if(height == null || height.length == 0)
return 0;
int left = 0;
int right = height.length - 1;
int max_area = 0;
int area = 0;
while(left < right){
if(height[left] > height[right]){
area = height[right] * (right - left);
right--;
}
else{
area = height[left] * (right - left);
left++;
}
if(area > max_area){
max_area = area;
}
}
return max_area;
}
}
int maxArea(vector<int>& height) {
int res = 0, l = 0, r = height.size() - 1;
while(l < r){
res = max(res, (r-l)*min(height[l], height[r]));
if(height[l] < height[r])
++l;
else
--r;
}
return res;
}
/*
* 贪心算法:从两边开始向中间缩小;每一步比较左右边界高度,高度小的那个向里走一步
*
* 这个贪心算法,为什么最优解不会被错过? 反证法 假设会被错过。
* 假设最优解是横坐标为x1,x2(x2在右边)的这两个点组成的
* 只考虑扫描到x2时,x1被错过的情况(x2被错过同理):
* 被错过指的是 当右指针向左扫描经过x2之后,左指针还在x1的左边P处时,x1被错过。
*
* 情况一 x2>p: x2会被保留,然后左指针向右移动到x1,x1不会被错过
* 情况二 x2<p: 小情况一:height[p]>height[x1] 则最优解为 p,x2而不是 x1,x2。 假设不成立
* 小情况二:p<=x1 最优解还是p,x2。 假设不成立
* //因为x2比p和x1都小,所以容器高度取决于x2,而p比x1偏左,所以p,x2比x1,x2面积大
*
*
*/
public int maxArea(int[] height) {
if(height.length<=2) return 0;
int left=0,right=height.length-1;
int maxArea=0;
while(left<right) {
int area = Math.min(height[left],height[right])*(right-left);
maxArea = Math.max(maxArea, area);
if(height[left]<=height[right]) {
left++;
}else {
right--;
}
}
return maxArea;
} public class Solution {
public int maxArea(int[] height) {
int len=height.length;
if(len==0){
return 0;
}
int maxW=0;
for(int i=0;i<len;i++){
for(int j=len-1;j>i;j--){
if(height[j]>=height[i]){
if(height[i]*(j-i)>maxW){
maxW=height[i]*(j-i);
}
break;
}
}
}
for(int i=len-1;i>0;i--){
for(int j=0;j<i;j++){
if(height[j]>=height[i]){
if(height[i]*(i-j)>maxW){
maxW=height[i]*(i-j);
}
break;
}
}
}
return maxW;
}
}
/*
* 目的:最大的容器能装多少水
* 方法:从两边逼近
*/
int maxArea(vector<int> &height) {
int maxVal = 0;
int left =0,right = height.size()-1;
while(left<right){
if (height[left]<=height[right]){
maxVal = max(maxVal,(right-left)*height[left]);
left++;
}
else{
maxVal = max(maxVal,(right-left) * height[right]);
right--;
}
}
return maxVal;
}
/*
思路:
双指针:头尾指针
头指针从前向后移动,尾指针从后向前移动。
计算头尾指针之间的面积,并于当前最大面积比较。
头尾指针总有一个指向较小值,因此可以每次都把指向较小值的指针进行移动。
*/
#include <algorithm>
class Solution {
public:
/**
*
* @param height int整型vector
* @return int整型
*/
int maxArea(vector<int>& height) {
int maxArea = 0;
//特殊情况检测
if(height.size()==0){
return maxArea;
}
int i=0;
int j=height.size()-1;
//头尾指针移动
while(i<j){
//用较短的作为宽
int wide = (height[i]>height[j])?height[j]:height[i];
//头尾指针的间隔是长
int length = j-i;
//计算面积
maxArea = max(length*wide,maxArea);
//将较短指针后移
if(height[i]<height[j]){
i++;
}else{
j--;
}
}
return maxArea;
}
}; import java.util.*;
public class Solution {
/**
*
* @param height int整型一维数组
* @return int整型
*/
public int maxArea (int[] height) {
// write code here
int sum=0,max=0;
for (int i = 0; i < height.length; i++) {
int count=1;
for (int j = i+1; j < height.length; j++) {
if(height[i]<height[j]) {
sum=count*height[i];
}else {
sum=count*height[j];
}
max=Math.max(sum, max);
count++;
}
}
return max;
}
} import java.util.*;
public class Solution {
/**
*
* @param height int整型一维数组
* @return int整型
*/
public int maxArea (int[] height) {
// write code here
int left = 0, right = height.length-1;
int res = 0;
while(left<right){
int h = height[left]<height[right]?height[left]:height[right];
if(res < h*(right-left)){
res = h*(right-left);
}
if(height[left]<height[right]) {
left++;
}else{
right--;
}
}
return res;
}
} class Solution {
public:
/**
*
* @param height int整型vector
* @return int整型
*/
int maxArea(vector<int>& height) {
int left = 0;
int right = height.size()-1;
int maxArea = 0;
while(left < right )
{
//最短
if(height[left] < height[right])
{
maxArea =max(maxArea,height[left]*(right-left));
left ++;//减少遍历次数
}else
{
maxArea =max(maxArea,height[right]*(right-left));
right --;//减少遍历次数
}
}
return maxArea; //编译减少错误
}
}; /**
*
* @param height int整型一维数组
* @return int整型
*/
function maxArea( height ) {
// write code here
if(!height){
return 0;
}
let max = 0;
let i = 0;
let j = height.length - 1;
while(i < j){
max = Math.max(max, (j-i)*Math.min(height[i],height[j]));
if(height[i] < height[j]){
i++;
}else{
j--;
}
}
return max;
}
module.exports = {
maxArea : maxArea
};