用Python刷LeetCode【53. 最大子序和(Maximum Subarray)】

嗯。。。过完春节了,开始捡起学习的进程(真香)。。。开始看mooc浙大的数据结构与算法(姥姥版)

C++我之前稍微接触了一点点,也仅仅是学到函数部分,唉,刷题不易,要是能刷过PAT的顶级,估计离合格的程序员也不远了吧?

总之。。。。新的一年,新的作死!

第一种解法:豹腻解法2

class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) == 1:
            return nums[0]
        join =[]
        for i in range(len(nums)):
            solu = []
            solu.append(nums[i])
            for j in range(i+1,len(nums)):
                solu.append(nums[j])
                #print(solu,sum(solu))
                join.append(sum(solu))
        if max(join) <= max(nums):
            return max(nums)
        return (max(join))

嗯,这个解法是O(n2)的。。。为嘛代码框不是黑底的了。。强迫症犯了。。

 

当然还有O(n)和O(logn)复杂度的,稍后开始尝试

 

第二种解法:累积遍历算法/在线处理/凸包算法(Graham扫描法)

(这居然是有证明的。。。一个统计学家提出来的)不会证明的数据分析师不是好程序员,我开始寻找这个算法的证明过程(莫名其妙涉及到了凸包算法)

https://www.cnblogs.com/nowgood/p/GrahamconvexHull.html 

为什么要把最大子序和当成凸包呢?这里给的是一个固定数组,为什么要在累计为0的时候舍弃前面的值呢?(小于0就会分裂成两块了)

https://blog.csdn.net/zwzsdy/article/details/80029796
https://blog.csdn.net/samjustin1/article/details/52043369

没有数学公式介绍确实真的不好看懂。。。这个数学问题是怎么转化的呢?

好吧。。。这个问题留给后人。。

那么我们来试一试这个方法

class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) == 1:
            return nums[0]
        solu,slide = 0,0
        for i in range(len(nums)):
            slide += nums[i]
            if slide > solu:
                solu = slide
            elif slide <= 0:
                slide = 0
        return solu

 额,理想很美好,然后就报错了,什么呢?就是全是负数的情况下,失效了,会输出0

这里有明显的一个bug就是遇到0便舍去,完全没有考虑到负数大小的排序

怎么改进这个算法确实想不清楚,最大的便捷成了最大的阻碍,姥姥你坑我!

 

那么下面继续试试

第三种解法:动态规划

class Solution:
    def maxSubArray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) == 1:
            return nums[0]
        cur = nums[:]
        maxSum = nums[0]
        for i in range(1,len(nums)):
            if cur[i-1] > 0:
                cur[i]= nums[i]+cur[i-1]
            if cur[i]>maxSum:
                maxSum = cur[i]
        return maxSum

 最关键的点是,用目前序列和对比目前指针位数字,如果大,则用目前指针位数字代替,非常的精妙,比小于0就舍弃不知道高到哪里去了。

第四种解法:分治法

分治法自己没有学过,看姥姥的用法是

class Solution(object):
    def maxSubArray(self, nums):
        left = 0
        right = len(nums)-1
        maxSum = self.divide(nums,left,right)
        return maxSum
        
    def divide(self,nums,left,right):
        if left==right:
            return nums[left]
        #  但是这里要注意要用取余,不然的话,指针不能读取浮点小数值
        center = (left+right)//2 
        leftMaxSum = self.divide(nums,left,center)
        rightMaxSum = self.divide(nums,center+1,right)
        leftBorderSum = nums[center]
        leftSum = nums[center]
        for i in range(center-1,left-1,-1):
            leftSum += nums[i]
            if leftSum>leftBorderSum:
                leftBorderSum = leftSum
        rightBorderSum = nums[center+1]
        rightSum = nums[center+1]
        for i in range(center+2,right+1):
            rightSum += nums[i]
            if rightSum>rightBorderSum:
                rightBorderSum = rightSum
        BorderSum = leftBorderSum + rightBorderSum
        return max(leftMaxSum,rightMaxSum,BorderSum)

更改自 https://blog.csdn.net/Jaster_wisdom/article/details/80662037 

。。。。。。目前只能做到领悟思想。。。。

我自己的想法是用log2(长度)先切成两辆一组的

但是这个迭代方法确实比自己先切方便。。。。总之就是有点懒了。。。。然后应该有更精妙的写法,等更新好了。。

2019/2/15 15:25:38

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值