LeetCode:Container With Most Water
2013-10-17 18:29
399 查看
/** 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. 题目大意:二维坐标轴上有n个点[i, ai],每个点画一条x轴的垂线(连接[i, ai]和[i, 0]),选两条线作为盆子装水,找出最多水的方案 **/ import java.util.*; public class Solution { public int maxArea(int[] height) { //return solve1(height); //超时 //return solve2(height); //想法错误 //return solve3(height); return solve4(height); } //================================ solve1 ======================================== //O(n^2) //双循环直接穷举,必然超时 private int solve1(int[] height){ int result = -1; int index = -1; for(int i=0; i<height.length; i++){ for(int j=i+1; j<height.length; j++){ index = i; if(height[i] > height[j]) index = j; int water = height[index] * (j-i); if(result < water) result = water; } } return result; } //================================ solve2 ======================================== //想法本身有问题,没能维护两点之间的宽度,算出来的果断是错误答案 //O(n * log2 n) = O(n * log2 n) + O(n) //先对数组进行排序,然后遍历,对于[i, ai],直接乘以他到最优的距离就可以得出当前点可容纳最多水的数量 private int solve2(int[] height){ Arrays.sort(height); int result = -1; int tmp = -1; for(int i=0; i<height.length; i++){ tmp = height[i] * (height.length - 1 - i); //注意这里要减1才能得到宽度 if(result < tmp) result = tmp; } return result; } //================================ solve3 ======================================== //O(m^2) = O(n) + O(n) + O(m^2) //搜索左端点 + 搜索右端点 + 查询并获取最大值 /** 考虑从这个题目本身的数学性质出发: 现在指定两点[i, ai],[j, aj],面积f(1)=(j-i)*min(ai, aj),固定左端点,移动右端点: 1、右端点右移,有两种情况: [j+k, b1],其中b1>=aj,则f(b1)=(j+k-i)*min(ai, b1),明显可得f(b1)>f(1); [j+k, b2],其中b2<=aj,则f(b2)=(j+k-i)*min(ai, b2),f(b2)和f(1)大小不定; 2、右端点左移,也有两种情况: [j-k, c1],其中c1>=aj,则f(b1)=(j-k-i)*min(ai, c1),f(c1)和f(1)大小不定; [j-k, c2],其中c2<=aj,则f(b2)=(j-k-i)*min(ai, c2),明显可得f(c2)<f(1); 左端点的情况和右端点对称,可以得出结论:如果程序从两端开始,向中间收缩,只能选择越来越高的点才能保证容量不变小。 例如,序列是[5(0),4(1),6(2),12(3),8(4),32(5),9(6),1(7),4(8)], 左端点i的选择只能是:0 -> 2 -> 3 -> 5 右端点j的选择只能是:8 -> 6 -> 5 可以从这一点出发,对水盆左右端点的情况进行缩减 **/ private int solve3(int[] height){ int[] leftPoint = new int[height.length]; int leftNum = 0; int[] rightPoint = new int[height.length]; int rightNum = 0; //选取左端点集合: for(int i=0, currentPoint=height[i]; i<height.length; i++){ if(height[i] >= currentPoint){ leftPoint[leftNum++] = i; currentPoint = height[i]; } } //选取右端点集合: for(int i=height.length-1, currentPoint=height[i]; i>=0; i--){ if(height[i] >= currentPoint){ rightPoint[rightNum++] = i; currentPoint = height[i]; } } //在所得的点里开始计算 //这里可以有一个优化的策略:当一端静止,另一端向其靠近,如果另一端的高度比这一端要高,那就可以结束当前循环了 int result = -1; for(int i=0; i<leftNum; i++){ for(int j=0; j<rightNum; j++){ //在这里可以加一个条件 int left = leftPoint[i]; int right = rightPoint[j]; if(left >= right) break; int width = right - left; //这里要用矮的那一个作为盆子的高度 int tall = min(height[left], height[right]); int water = tall * width; if(result < water) result = water; } } return result; } //================================ solve4 ======================================== //O(n) //左右靠拢,到中间合并的时候必然可得最大值 /** 现在试试左右两端往中间收窄的策略: 当固定其中一端i,另一端j向其靠近,如果发现 height[j] >= height[i]; 那么这个时候j就不需要在靠近了,因为即使在靠近,高度也限制在i点上,无法增加, 此时应固定j点,转由i点向j点靠近。 同时对中间每一步产生的容量值进行计算,得出最大值。 其实使用了solve3的一些结论,在这里只移动矮的那一边,因为移动高的那一边没有意义 计算完毕之后一定能得到最大值 **/ private int solve4(int[] height){ int left = 0; int right = height.length - 1; int result = -1; while(left < right){ int tmp = (right - left) * min(height[left], height[right]); result = max(result, tmp); if(height[left] <= height[right]) left++; else right--; } return result; } private int min(int a, int b){ if(a < b) return a; else return b; } private int max(int a, int b){ if(a < b) return b; else return a; } }
相关文章推荐
- [LeetCode]Container With Most Water
- LeetCode – Refresh – Container With Most Water
- leetcode 11 Container with Most Water
- [LeetCode]Container With Most Water
- Leetcode: Container With Most Water
- Container With Most Water (隔板如何蓄水) 【leetcode】
- LeetCode-11-Container With Most Water(C语言实现)
- LeetCode——Container With Most Water
- Leetcode-container-with-most-water
- [LeetCode] 最大容器问题 Container with Most Water
- 7 Container With Most Water_Leetcode
- [Leetcode 43] 11 Container With Most Water
- Leetcode 11-Container With Most Water
- LeetCode11-Container With Most Water
- [LeetCode][JavaScript]Container With Most Water
- LeetCode——Container With Most Water
- LeetCode(11)题解: Container With Most Water
- [leetcode] Container With Most Water
- leetcode----Container With Most Water
- [LeetCode]11 Container With Most Water