Leetcode个人题解11

LEETCODE专题


11. Container With Most Water

题目要求:
这里写图片描述

这里要求我们将数组中的每个元素(下标为i,从1开始)看成一条向量,起点为(i, 0), 终点为(i, a[i]),这样每条向量的长度就是a[i]。然后再找出这些向量中的两条,使它们和x轴形成的容器面积最大。当然不允许倾斜向量。


问题:

  1. 如何计算容器的面积?
  2. 如何减少时间复杂度?

思路:

  1. 计算容器的面积,我们需要明白“木桶效应”——在所有组成木桶的木材中,最短的那根对木桶装的水量起着决定性作用。这里也是一样,我们计算容器的面积,其实也就是计算一个长方形的面积。假设i、j分别是这两条向量的下标且i是a[i] < a[j],那么宽就是两条向量在x轴上的投影点的距离,也就是下标的差;长则是两条向量中最短的那条向量的终点的y值,也就是a[i]。
  2. 这里笔者曾经使用过两重循环。后来发现这种解法十分的naive,时间复杂度为O(n^2)的算法分分钟超时。于是改进了一下思路,发现,其实这和快速排序算法十分的相似,即刚开始选定第一条向量和最后一条向量,然后让长度较短的一条向量的下标往另一个下标靠拢,若移动的过程中得到的新的向量的长度比之前的短,继续移动,直到得到的向量的长度更长为止,此时记录新的容器面积,得到的倘若比最大面积大的话就覆盖最大面积。这里之所以可以抛弃长度更短的向量,是因为下标在移动的过程中本身宽就在减少,由上面的讨论可知,此时长由该向量长度决定,若得到的长度更短,容器面积自然也更小,也就没有记录新的容器面积的必要了。

下面直接上代码:

class Solution {
public:
    int maxArea(vector<int>& height) {
        /*
         * 1 loop.
         * Firstly initial the maxArea to be
         * the area of the container formed
         * by the first line and the last
         * line. Then let index of the shorter
         * line goes closer to the longer one.
         *
         * Record the area each time it finds
         * a larger one.
         *
        */
        int width, length, index;
        int maxArea = -1;
        int left = 0, right = height.size() - 1;
        do {
            width = right - left;
            if (height[left] < height[right]) {
                length = height[left];
                index = left;
                while (left < right && height[left] <= length) left++;
            } else {
                length = height[right];
                index = right;
                while (left < right && height[right] <= length) right--;
            }
            maxArea = maxArea > width * length ? maxArea : width * length;
        } while (left < right);

        return maxArea;
    }
};

时间复杂度:O(n)

猜你喜欢

转载自blog.csdn.net/m0_37576233/article/details/78721855