leetcode力扣盛最多水的容器-最大容器问题

leetcode盛最多水的容器-最大容器问题如下

在这里插入图片描述

问题分析:此题就是,有哪两条边围成的容器,可以盛更多的水。这里的边即是上图中的每根柱子,也就是数组中元素对应的值,所以容器的高取决于较低的那个柱子,因为水若没过会从上流出,容器的宽度取决于两根柱子之间的长度

故问题可简化为求数组中 Min(a[i],a[j]) × | i-j | 的最大值; a[i],a[j]为上图中i,j任意两点的对应的柱子;

解决思路: 我们可以看到上诉图或者公式中,容器的高度取决于较低的那个柱子,当我们选择一个最低的柱子i = 0时,其他任何柱子都比其高,所以容器的高度即是a[0]它本身的高度值,它要想组成一个最大的容器,必须找它最远距离的柱子,也就是最后一个;
在这里插入图片描述
我们继续观察第二低的柱子,也就是第4根,对于它来说,除了第一根柱子,其他柱子都比它高,所以高度值又是一定的,所以要想组成最大容器,还是找最远的柱子即可,第一根不必再考虑,因为它与第一根所围成的容器已包含在第一根考虑的情况中,一定小于或等于第一根最大情况的值
在这里插入图片描述
这样剩余的每一根柱子,只用考虑比自己不比自己低的柱子中,哪个距离自己最远即可,这可以称为该柱子的最优辅柱 (‘’辅柱‘’是我自己瞎起的,意思就是只帮着自己完成另一边的盛水工作,还不坑自己,不会漏水)

最后,其实只需遍历一遍,找到每根柱子的“最优辅柱”即可,算一下哪根柱子跟自己的“最优辅柱”配合得好,盛的水最多。

算法实现: 然而如何找到每一根柱子的“最优辅助”呢?寻找最远不比自己低的柱子,最快的方法就是从两头开始,也就是数组的头部和尾部,因为两头距离最长;

当第一根柱子与最后一根柱子相遇时,最后一根柱子比第一根要高,所以它可以被称为第一根柱子的“辅柱”,并且它还距离第一根柱子最远,故它是第一根柱子的“最优辅柱”,第一根柱子找到了最优辅柱就不用在考虑第一根柱子了;
然后再移到第二根,它与最后一根相遇时,判断一下谁是谁的“辅柱”呢?没错,第二根比最后一根高,所以它是最后一根柱子的“最优辅柱”,然后继续比较倒数第二根;

这样只要从两头开始,两根柱子相遇,它们其中一根必是另一根的“最优辅柱”,然后两头依次往中间移动,最后当所有的柱子都被遍历完后,除了最高的柱子,每根柱子都会有其“最优辅柱”,最高的柱子可能是多个柱子的“最优辅柱”,而且可能因为自身太高,太强,没有与其对应的辅柱(谁和其搭配都会漏水),不过它的最优情况已包含在之前的柱子中,所以不必考虑。
最后将所有的“最优辅柱”所搭配的值相比较,即可得到最优的解,这些可以在移动过程中进行比较

以上柱子两头移动比较的方法,也是双指针算法的一种,两头为两个指针,逐步比较,然后向中心移动。

Java实现方法:

import java.util.Random;
public class findTheMax {
    public static void main(String[] args){
             Integer[] testArrays = getArray(5);
             FindThemax(testArrays);
    }
    static Integer[]  getArray(int n){         //此函数为生成并返回一个随机数数组(可忽略),n为数组大小
        Random r = new Random(521);
        Integer[] Arrays = new Integer[n];
        for(int i=0;i<n;i++){
            Arrays[i] = r.nextInt(100);
            System.out.print(Arrays[i]+",");
        }
        System.out.println("");
        return Arrays;
    }
    static void FindThemax(Integer[] arrays){		//该问题寻找最大解的主函数
        int i = 0,j = arrays.length-1;							//放置两头指针
        int theMax = 0;	
        while(i<j){														//判断指针是否到中心相遇
            if(arrays[i]<arrays[j]){								//对两根柱子高度进行比较
                theMax = Math.max(theMax, arrays[i] * (j - i));		//选择头部柱子的“最优辅柱”解,比较与之前已算柱子解的最大值
                i++;															//向后一根柱子移动
            }else {
                theMax = Math.max(theMax, arrays[j] * (j - i));  	//选择尾部柱子的“最优辅柱”解,比较与之前已算柱子解的最大值
                j--;															//向后一根柱子移动
            }
        }
        System.out.println("The max value is "+theMax);   //输出最大解;
    }
}

FindThemax函数中,while循环只将该数组遍历了一遍,进行比较操作,所以该程序的时间复杂度为O(n);

总结: 该问题是一个双指针算法问题,通过普通方法,进行两层for循环遍历所有数组元素,将每一个柱子一一相结合计算容器大小也可以实现,但是会有计算冗余,因为其中有一部分不必再计算,可以省略,就是当Min(a[i],a[j])固定为a[i]时,a[j]的大小不必考虑,i-j只需找到最远的即可,双指针就是简化省略了这部分的计算。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值