盛最多的水

244 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

盛最多的水

image.png

  1. 面积计算公式 : min(height[a],height[b])*(b-a)

方法一:暴力枚举

  1. 双层for,找出所有的可能的面积,选出最大值
  2. 缺点:时间复杂度高 n^2,leetcode运行不通过
/**
     * 双层for循环,一个一个找,找出所有的组合的最大值,时间复杂度比较高
     *
     * @param height
     * @return
     */
    public static int maxArea(int[] height) {
        int max = 0;
        //注意:以下这种双层for能保证i和j不重复,且不会有反复的组合
        for (int i = 0; i < height.length - 1; i++) {
            for (int j = i + 1; j < height.length; j++) {
                //计算面积,比较最大值
                int area = (j - i) * Math.min(height[i], height[j]);
                max = Math.max(area, max);
            }
        }
        return max;
    }

方法二:左右指针向中间收敛

  1. 创建左右指针,分别位于左右两侧。
  2. 每次将较矮的那个指针向中间移动,为什么呢,因为向中间移动后,(b-a)是变短了的,所以只有移动比较矮的那个指针,才有可能找到比较大的面积。
 /**
     * for循环,用两个指针从数组的两侧进行收敛,找出最大的面积
     * <p>
     * 找出数组中所有的组合的最大值
     *
     * @param height
     * @return
     */
    public static int maxArea2(int[] height) {
        int max = 0;
        int left = 0;
        int right = height.length - 1;
        while (left < right) {
            //计算面积
            int area = (right - left) * Math.min(height[right], height[left]);
            //比较面积
            max = Math.max(area, max);
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        return max;
    }
​
 /**
     * 优化maxArea2中的代码,使其更加优雅
     *
     * @param height
     * @return
     */
    public static int maxArea3(int[] height) {
        int max = 0;
        int left = 0;
        int right = height.length - 1;
        while (left < right) {
            //这里注意三元表达式中 left++ 和right-- 需要在 * 号的后面
            int area = height[right] > height[left] ?
                    (right - left) * height[left++] : (right - left) * height[right--];
            max = Math.max(area, max);
        }
        return max;
    }