动态规划 | 贪心 | 分治算法 :力扣53. 最大子序和

1、题目描述:

动态规划 | 贪心 | 分治算法 :力扣53. 最大子序和_第1张图片

2、题解:

方法1:暴力法 超时
枚举

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        #暴力法
        res = nums[0]
        for i in range(0,len(nums)):
            sum_ = 0
            for j in range(i,len(nums)):
                sum_ += nums[j]
                res = max(res,sum_)
        return res

方法2:动态规划
动态规划问题,弄清楚三点:

1、重复子问题;
2、最优子结构;
3、无后效性。

动态规划:

1、状态定义;
2、状态转移方程;
3、初始化;base case
4、输出;
5、思考状态压缩。

可以用递归去求,但是会存在重叠子问题,加个备忘录可以解决重复问题。
思路:

状态定义:
dp[i],表示以nums[i]为结尾的最大子序和
状态转移方程:
dp[i]=max(nums[i],dp[i-1]+nums[i])
初始化:
dp[:] = float('-inf')
返回值:
max(dp) 在所有结尾中最大的子序和

代码如下:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
	#动态规划
	dp = [float('-inf')] * len(nums)
	dp[0] = nums[0]
	for i in range(1,len(nums)):
	    dp[i] = max(nums[i],dp[i-1] + nums[i])
	return max(dp)

空间优化:
上面的空间复杂为O(N),因为dp[i]只与前面的dp[i-1]有关,所以我们可以不用数组,只用一个变量来记录,优化后,空间复杂度为O(1)

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        #动态规划
        res = nums[0]
        dp= nums[0]
        for i in range(1,len(nums)):
            dp = max(nums[i],dp + nums[i])
            res = max(res,dp)
        return res

方法3:贪心
遍历,sum_是数字之和,如果sum_ > 0,则就加上nums[i],否则 就把nums[i]赋值给sum_,取res和sum_较大的值

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        #贪心
        res = nums[0]
        sum_ = 0
        for num in nums:
            if sum_ > 0:
                sum_ += num
            else:
                sum_ = num 
            res = max(res,sum_)
        return res

方法4:分治
最大子序和要么在左边,要么在右边,要么通过中间,前两种情况是可以递归处理的,第三种情况可以直接计算出来

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        #分治
        n = len(nums)
        #终止条件
        if n == 1:
            return nums[0]
        else:
            left = self.maxSubArray(nums[0:len(nums) // 2])
            right = self.maxSubArray(nums[len(nums) // 2 : len(nums)])
        max_1 = nums[len(nums) // 2 - 1]
        temp = 0
        for i in range(len(nums) // 2 - 1,-1,-1):
            temp += nums[i]
            max_1 = max(temp,max_1)
        max_r = nums[len(nums) // 2]
        temp = 0
        for i in range(len(nums) // 2,len(nums)):
            temp += nums[i]
            max_r = max(temp,max_r)
        return max(right,left,max_1 + max_r)

3、复杂度分析:

方法1:
时间复杂度:O(N^N)
空间复杂度:O(1)
方法2:
时间复杂度:O(N)
空间复杂度:O(1)
方法3:
时间复杂度:O(N)
空间复杂度:O(1)
方法4:
时间复杂度:O(N)
空间复杂度:O(logN)

你可能感兴趣的:(LeetCode高频面试题)