leetcode-java.T011_ContainerWithMostWater 找两条竖线然后这两条线以及X轴构成的容器能容纳最多的水

本文详细解析了LeetCode第11题“盛最多水的容器”的算法实现,通过贪心算法寻找两竖线与X轴形成的容器所能容纳的最大水量,并提供了两种解题思路的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

敬请关注博客,后期不断更新优质博文,谢谢

每天坚持刷leetcode----找两条竖线然后这两条线以及X轴构成的容器能容纳最多的水

 

package leetcode.T011_ContainerWithMostWater;
/**   
 * @Title: Solution.java 
 * @Package leetcode.T011_ContainerWithMostWater 
 * @Description: TODO 
 * @author zhouzhixiang  
 * @date 2017-6-4 上午12:56:28 
 * @version V1.0   
 */
public class Solution {

	 /**
     * <pre>
     * 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.
     *
     * 题目大意:
     * 找两条竖线然后这两条线以及X轴构成的容器能容纳最多的水。
     *
     * 解题思路:
     * 使用贪心算法,
     *      1.首先假设我们找到能取最大容积的纵线为 i, j (假定i<j),
     *      那么得到的最大容积 C = min( ai , aj ) * ( j- i) ;
     *
     *      2.下面我们看这么一条性质:
     *          ①: 在 j 的右端没有一条线会比它高!假设存在 k |( j<k && ak > aj) ,
     *          那么  由 ak > aj,所以 min(ai, aj, ak) =min(ai, aj) ,
     *          所以由i, k构成的容器的容积C' = min(ai, aj) * (k - i) > C,
     *          与C是最值矛盾,所以得证j的后边不会有比它还高的线;
     *
     *          ②:同理,在i的左边也不会有比它高的线;这说明什么呢?
     *          如果我们目前得到的候选: 设为 x, y两条线(x< y),那么能够得到比
     *          它更大容积的新的两条边必然在[x, y]区间内并且 ax' >= ax , ay' >= ay;
     *
     *      3.所以我们从两头向中间靠拢,同时更新候选值;在收缩区间的时候优先从
     *      x, y中较小的边开始收缩;
     * </pre>
     *
     * @param height
     * @return
     */
	 public static void main(String[] args) {
			int[] a = {11,22,31,14,15};
			int result = new Solution().maxArea2(a);
			System.out.println(result);
	 }
	 
	 // 参考(不如自己写的简便)
	 public int maxArea(int[] height) {

        // 参数校验
        if (height == null || height.length < 2) {
            return 0;
        }


        // 记录最大的结果
        int result = 0;

        // 左边的竖线
        int left = 0;
        // 右边的竖线
        int right = height.length - 1;

        while (left < right) {
            // 设算当前的最大值
            result = Math.max(result, Math.min(height[left], height[right]) * (right - left));
            // 如果右边线高
            if (height[left] < height[right]) {
                int k = left;
                // 从[left, right - 1]中,从左向右找,找第一个高度比height[left]高的位置
                while (k < right && height[k] <= height[left]) {
                    k++;
                }

                // 从[left, right - 1]中,记录第一个比原来height[left]高的位置
                left = k;
            }
            // 左边的线高
            else {
                int k = right;
                // 从[left + 1, right]中,从右向左找,找第一个高度比height[right]高的位置
                while (k > left && height[k] <= height[right]) {
                    k--;
                }

                // 从[left, right - 1]中,记录第一个比原来height[right]高的位置
                right = k;
            }
        }

        return result;
    }
	
	/**
	 * 
	* @Title: maxArea2 
	* @Description: daniel
	* @param @param height
	* @param @return    
	* @return int    
	* @throws
	* 
	* 解题思路:让所有的值都遍历出来,乘积比较下大小
	 */
	 public int maxArea2(int[] height){
		 
		 int left = 0;
		 int right = height.length-1;
		 int result = 0;
		 
		 while(left<right){
			 
			 left++;
			 
			 while(left<right){
				 
				 result = Math.max(result, (right-left)*Math.min(height[left], height[right]));
				 right--;
			 }
		 }
		 
		 
		 
		 return result;
	 }
	 
	
}

欢迎加入Java猿社区
 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值