LeetCode:: Container with most water

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.

 

题目分析:

1、初看题目是O(N*N)的时间复杂度。输入为N,在N个元素中挑出两个元素,组成的梯形面积来盛水,注意短板效应。所以水量由横向距离W和两板中的短板高度H决定。C(N,2)中种组合,如果全部列举出来求最大值的话,复杂度为N*(N-1)/2。时间复杂度为O(N*N)

2、O(N)的解法,思想非常巧妙。输入为N,下标为0--N-1,输入内容为 Height[0--N-1]。根据水量由W和H决定。要求水量最大,设此区间的起点为begin, 终点为end, 则首先是的W最大,即begin = 0, end = N-1, 此时求得面积 max_area。之后想想,往中间靠的过程,W必定减小,而要使得max_area有可能增大,则只能要求H增大,才有可能。即begin和end中的短板需要得到提升。提升的过程是往中间靠拢的过程。

3、尝试写一段伪代码。其实正确逻辑的伪代码是至关重要的。这会使得之后的编程变得容易许多。思路也清晰。

MaxArea(Height[0--N-1]) {
    max_area = 0, begin = 0, end = N-1;
    while(begin < end) { // 当begin >= end 时,重复不必要的计算
       max_area = FindMax(前一刻最大,当前最大)
       // 对begin和end 进行更新
       if(Heigt[begin] < Height[end])
              begin++;
          else
              end--; 
   }
}

4、代码很简单,主要在于用这种思路去除了c(n,2)中的很多没有必要判断的情况。最好的情况循环N/2次,最差的情况也只是循环N次。

// 看了参考的思路
// 计算面积需要有两个点的位置。通常的思路是从左边开始往右寻找
// 这个想法,从左右边界同时开始,记录最大值。贪心算法,当左右边界时j-i的值最大
// 向中间靠拢的过程i和j之间的距离变小,要使得面积更大,则要寻找更高的短板。
// 所以从小的一侧往中间搜索,知道i,j相遇,即完成了所有最大值的搜索工作
int Solution::maxArea2(vector<int> &height) {
	int len = height.size();
	if(len < 2) return 0;
	int begin = 0, end = len-1, max_area = 0;
	while(begin < end) { // 当begin == end 时,面积为0,不需要计算
		max_area = max(max_area, (end-begin)*min(height[begin], height[end]));
		// 寻找下一个可能的面积
		if(height[begin] < height[end])
			begin++;
		else end--;
	}
	return max_area;
}

  

 

posted on 2014-04-25 09:19  themo  阅读(543)  评论(0编辑  收藏  举报

导航