LeetCode11 Python Container With Most Water

LeetCode11 Python Container With Most Water 解法总结

  • 题目
  • 解法1: 暴力遍历法
  • 解法2
  • 解法3: Two Pointer Approach

题目

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.
Example:
Input: [1,8,6,2,5,4,8,3,7]
Output: 49
Note: You may not slant the container and n is at least 2.

Container With Most Water

解法1: 暴力遍历法

这道题拿到手最容易想到的方法就是暴力遍历,不需要任何推理和技巧算法,全枚举出来最大值一定在里面,但是暴力遍历的时间复杂度是quardratic的。虽然用的语句结构和Java一样,但我的Python Brute Force解法一直都是Time Limit Exceeded,一直无法通过最后几个超长的test case,于是放弃之。

class Solution:
    def maxArea(self, height: List[int]) -> int:
        res = 0
        for i in range(len(height)-1):
            for j in range(i+1, len(height), 1):
                res = max(res, min(height[i], height[j]) * (j-i))
        return res

时间复杂度: O ( n 2 ) \Omicron(n^2) O(n2). Calculating area for all n ( n + 1 ) 2 {n(n+1)}\over2 2n(n+1) height pairs.
空间负责度: O ( 1 ) \Omicron(1) O(1). Constant extra space is used.

解法2

第二个想法是所算面积是取两条线中短的那一根✖️两条线间的距离。所以重要的信息是两条线的x坐标差以及短线的高度,将list排序,假设排序后的list为 [ a 1 , a 2 , . . . , a n ] [a_1, a_2, ..., a_n] [a1,a2,...,an] a n − 1 a_{n-1} an1只会是 a n a_n an的短板, a n − 2 a_{n-2} an2只会是 a n − 1 , a n a_{n-1}, a_n an1,an的短板,依次类推。如果要找到以 a x a_x ax为短板的最大面积,我们只要在 a x + 1 , . . . , a n − 1 , a n a_{x+1}, ..., a_{n-1}, a_n ax+1,...,an1,an中找哪根线和 a x a_x ax有最大的x坐标差。

class Solution:
    def maxArea(self, h: List[int]) -> int:
        from operator import itemgetter
        lenh = len(h)
        # if h = [1,8,6,2,5,4,8,3,7]
        # sortedh = [(0, 1), (3, 2), (7, 3), (5, 4), (4, 5), (2, 6), (8, 7), (1, 8), (6, 8)]
        sortedh = sorted(enumerate(h), key=itemgetter(1))
        maxArea = sortedh[lenh-2][1]*abs(sortedh[lenh-1][0]-sortedh[lenh-2][0])
        if (lenh == 2): 
            return maxArea
        for i in range(lenh-3, -1, -1):
            limh = sortedh[i][1] # 短板的高度
            limx = sortedh[i][0] # 短板在原list的索引值,也可以理解为x坐标值
            if (max(limh*limx,limh*(lenh-1-limx)) > maxArea):
                maxw = 0
                for j in range(i,lenh):
                    tempw = abs(sortedh[j][0]-limx)
                    if (tempw > maxw): # 寻找和短板的最大x坐标差
                        maxw = tempw
                tempArea = limh * maxw # 以limh为短板的最大面积
                if (tempArea > maxArea):
                    maxArea = tempArea
        return maxArea

sortedh里面的element为tuple (x, y),x为排序后的数值,y为其在原list的索引值。刚开始提交的解法还是超出时间限制,后来修改补上了if (max(limh*limx,limh*(lenh-1-limx)) > maxArea):终于通过。这句话的意思是如果短板高度✖️max(与第一个元素的坐标差,与最后一个元素的坐标差) < maxArea,则tempArea不可能超过maxArea,算是减少了一些处理时间。

解法3: Two Pointer Approach

使用两个指针,一前一后。初始时,一个指向list开头,一个指向list结尾。先粘一下官网的解释:

The intuition behind this approach is that the area formed between the lines will always be limited by the height of the shorter line.
Further, the farther the lines, the more will be the area obtained. We take two pointers, one at the beginning and one at the end of the
array constituting the length of the lines. Futher, we maintain a variable maxarea to store the maximum area obtained till now.
At every step, we find out the area formed between them, update maxarea and move the pointer pointing to the shorter line towards the other end by one step.

官网还放了动图来模拟解题的过程,因为所算面积是取两条线中短的那一根✖️两条线间的距离。这次从两条线间的距离入手,首先两个指针一个指头一个指尾,这时可获得最大线间距,并获得一个面积值。下一步,指针将被挪动一格,线间距减1,此时我们希望在指针挪动后获得一个较高的短板,因此该将指向短线的指针向内挪动(如果移动指向长线的指针,两种情况,移动后该指针指向的线高于短线,短线仍然是短板,但线间距比上一步还小,面积自然不可能被更新,另一种情况,移动后指向的线低于等于短线,那么面积将会更小——较上一步,短板更矮,间距更小)。

class Solution:
    def maxArea(self, h: List[int]) -> int:
        l = 0;
        r = len(h)-1
        maxArea = 0
        while (l < r):
            tempArea = (r-l)*min(h[l],h[r])
            if (tempArea > maxArea):
                maxArea = tempArea
            if (h[l] < h[r]):
                l += 1
            else:
                r -= 1
        return maxArea

时间复杂度: O ( n ) \Omicron(n) O(n). Single pass.
空间负责度: O ( 1 ) \Omicron(1) O(1). Constant space is used.

官网解答

你可能感兴趣的:(刷题笔记,leetcode,指针,数据结构)