• leetcode_11. Container With Most Water


    leetcode_11. Container With Most Water

    一,问题:

    Given n non-negative integers a1a2, ..., an, where each represents a point at coordinate (iai). n vertical lines are drawn such that the two endpoints of line i is at (iai) 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 and n is at least 2.

    翻译:

    给定n个非负整数a1,a2,...,an,其中每个代表坐标(i,ai)处的一个点。 绘制n条垂直线,使得线i的两个端点处于(i,ai)和(i,0)处。 找到两条线,它们与x轴一起形成一个容器,以使容器包含最多的水。

    注意:您不得倾斜容器(即木板效应),并且n至少为2。

     

    二,思路:

    1,暴力法:直接通过双重循环遍历,找出结果。

    2,等值线法:其实还是针对法的翻版,找出n1对应的n2等值线,从而针对找寻对应获得最大值的n2。

     

    三,代码:

    1.V1:

    func maxArea(height []int) int {
        maxarea:=0
        for k:=0;k<len(height)-1;k++{
            for k2:=k+1;k2<len(height);k2++{
                minheight:=height[k]
                if height[k2]<height[k]{
                    minheight=height[k2]
                }
                smaxarea:=(k2-k)*int(minheight)
    
                if smaxarea>maxarea{
                    maxarea=smaxarea
                }
            }
        }
        return maxarea
    }

    Runtime:648ms,15.04%

    根据上一次的经验,我将第二个遍历从右边开始。因为这样出现更大结果的可能性更高。

    并且将内部一些方法提取出去。

    最重要的是方法提取出去后,我可以节省一定的内存(如smaxarea)。

    2.V2:

    func maxArea(height []int) int {
        maxarea:=0
        for k:=0;k<len(height)-1;k++{
            for k2:=len(height)-1;k2>k;k2--{
                maxarea=max(maxarea,(k2-k)*min(height[k],height[k2]))
            }
        }
        return maxarea
    }
    
    func min(a,b int) int {
        if a<b{
            return a
        }else{
            return b
        }
    }
    
    func max(a,b int) int {
        if a>b{
            return a
        }else{
            return b
        }
    }

    Runtime:592 ms,23.31%

    虽然有所提高,但是依旧差距很大。所以必然存在巨大性能的提升点。

    经过思考,我想到一个特性,当我在第二个循环内找到的高度比第一个循环内的高度高时,那么这次计算的结果必然是第二个循环这个循环中最大的结果,我就可以break了。这样我将会节省巨大的时间。

    原因是我水桶矩形的高度最高也就是第一个循环中的高度(取最小值嘛),宽度必然是逐步减小的。(我是从两边往中间遍历的)

     

    3.V3:

    func maxArea(height []int) int {
        maxarea:=0
        for k:=0;k<len(height)-1;k++{
            for k2:=len(height)-1;k2>k;k2--{
                
                if height[k]<height[k2]{
                    maxarea=max(maxarea,(k2-k)*height[k])
                    break
                }else{
                    maxarea=max(maxarea,(k2-k)*height[k2])
                }
            }
        }
        return maxarea
    }
    
    func max(a,b int) int {
        if a>b{
            return a
        }else{
            return b
        }
    }

    Runtime:112 ms,33.83%

    也许比例提高不多,但是实际运行时间直接提高了五倍。这简直是跨越性的提升。

    为了代码可读性,以及小的修改,让我简单地整理一下代码。

     

    4.V4:

    func maxArea(height []int) int {
        maxarea:=0
        for left:=0;left<len(height)-1;left++{
            for right:=len(height)-1;right>left;right--{
    
                if height[left]<height[right]{
                    maxarea=max(maxarea,(right-left)*height[left])
                    break
                }else{
                    maxarea=max(maxarea,(right-left)*height[right])
                }
            }
        }
        return maxarea
    }
    
    func max(a,b int) int {
        if a>b{
            return a
        }else{
            return b
        }
    }

    Runtime: 104 ms,33.83%

    小有提升,关键这样看起来很舒服。

     

    四,他人代码:

    1.最佳代码:

    func min(a, b int) int {
        if a < b {
            return a
        }else{
            return b
        }
    }
    
    func max(a, b int) int {
        if a < b {
            return b
        }else{
            return a
        }
    }
    
    func maxArea(height []int) int{
        area, left, right := 0, 0, len(height)-1
        for left < right {
            h := min(height[left], height[right])
            area = max(area, h*(right-left))
            for ; left < right && height[left] <= h; left++{
            }
            for ; left < right && height[right] <= h; right--{
            }
        }
        return area
    }

    Runtime:16ms,100%

    2.分析:

    其实这里面,有两处很精彩。

    首先是循环判断条件 left<right。这个条件的精彩之处是它与之前代码中

     if height[left]<height[right]{
                    maxarea=max(maxarea,(right-left)*height[left])
                    break
                }else{
                    maxarea=max(maxarea,(right-left)*height[right])
                }

    的良好配合。从两个方面节省了时间。可惜我只注意到了其在第二个循环的价值。并没有将之联系到第一个循环。在理解这点之后,我完善了自己的代码:

    V5:

    func maxArea(height []int) int {
        length:=len(height)
        left,right,maxarea:=0,length-1,0
        for ;left<right;left++{
            for {
    
                if height[left]<=height[right]{
                    maxarea=max(maxarea,(right-left)*height[left])
                    break
                }else{
                    maxarea=max(maxarea,(right-left)*height[right])
                }
                right--
            }
        }
        return maxarea
    }
    
    func max(a,b int) int {
        if a>b{
            return a
        }else{
            return b
        }
    }

    Runtime: 20 ms,82.71%

    这两个语句结合起来,就从内外两个循环节省时间了。需要好好理解。

    (由于最近很忙,忙得有的博客都写得差不多了,却没时间修饰一下。估计之后博客会写得比较粗糙一些。)

  • 相关阅读:
    atitit.为什么技术的选择方法java超过.net有前途
    HDU 4022 Bombing STL 模拟题
    定制XP引导屏幕背景图像和替换windows这句话
    《STL源代码分析》---stl_heap.h读书笔记
    2015在大型多人在线游戏市场报告
    于Unity3D调用安卓AlertDialog
    jQuery整理笔记5----jQuery大事
    推断字符串数组里面是空的
    软测试-数据结构
    2014第18周三
  • 原文地址:https://www.cnblogs.com/Tiancheng-Duan/p/9112462.html
Copyright © 2020-2023  润新知