0053.maximum-sum-subarray

    技术2022-07-12  78

    from typing import List import sys #--------testcase input--------- nums1 = [-2,1,-3,4,-1,2,1,-5,4] nums2 = [1] nums3 = [-2,1] nums4 = [-1,-2] nums5 = [-1,-2,-3,-4,-5,-6,-7] nums6 = [-1,-2,-3,1,-5,-6,-7] #----------------------------main function-------------------------------- # V1.0 暴力解法(LeetCode超时) #时间复杂度:O(n^3) #空间复杂度:O(1) # def maxSubArray(nums: List[int]) -> int: # if nums: # maxsum = nums[0] # for i in range(len(nums)): # for j in range(i,len(nums)): # tmpsum = 0 # for k in range(i,j+1): # tmpsum += nums[k] # maxsum = max(tmpsum, maxsum) # return maxsum # else: # return 0 # V1.1 暴力解+前缀和(LeetCode超时) #时间复杂度:O(n^2) #空间复杂度:O(1) # def maxSubArray(nums: List[int]) -> int: # if nums: # maxsum = -sys.maxsize # for i in range(len(nums)): # tmpsum = 0 # for j in range(i,len(nums)): # tmpsum += nums[j] # maxsum = max(tmpsum, maxsum) # return maxsum # else: # return 0 # V1.2 优化前缀和 #时间复杂度:O(n) #空间复杂度:O(1) # def maxSubArray(nums: List[int]) -> int: # if nums: # if len(nums) == 1: # return nums[0] # else: # S = [0]*len(nums) # S[0] = nums[0] # minS = 0 #minS要赋0 # maxsum = S[0] #maxsum初值赋S[0],是为了考虑当最大子序为num[0]时(如[-1,-2]);因为下面的循环直接从S[1]开始考虑,即下面循环出来的最大子序,结束index一定>=1,不会考虑到最大子序为S[0]的情况 # for i in range(1,len(nums)): # S[i] = S[i-1] + nums[i] # if minS > S[i-1]: # minS = S[i-1] #注意minS应是S[0]~S[i-1]中的最小值,而不是S[0]~S[i] # maxsum = max(maxsum,S[i]-minS) # return maxsum # else: # return 0 # V1.2.1 优化前缀和,比较聪明的写法 #时间复杂度:O(n) #空间复杂度:O(1) # def maxSubArray(nums: List[int]) -> int: # sum = minSum = 0 #minSum要赋0 # maxSum = nums[0] #maxSum初值赋S[0],是为了考虑当最大子序为num[0]时(如[-1,-2]);因为下面的循环直接从S[1]开始考虑,即下面循环出来的最大子序,结束index一定>=1,不会考虑到最大子序为S[0]的情况 # for i in range(len(nums)): # sum += nums[i] # maxSum = max(maxSum,sum-minSum) # minSum = min(sum,minSum) #注意在用sum-minSum表示nums[0:i]中的最大子序和时,minSum应是nums[0:i-1]中的最小子序和;所以要把minSum=...放在求sum-minSum之后! # return maxSum # V1.3 分治法 #时间复杂度:O(nlogn) n是数组长度 #空间复杂度:O(logn) 因为调用栈的深度最多是logn # def maxSubArray(nums: List[int]) -> int: # if len(nums) == 1: # return nums[0] # elif len(nums) == 2: # return max(nums[0]+nums[1],max(nums[0],nums[1])) # midIdx = (len(nums))//2 # Lmax = maxSubArray(nums[:midIdx]) #左闭右开,要用midIdx而不是midIdx-1;LeetCode里要改成self.maxSubArray # Rmax = maxSubArray(nums[midIdx+1:]) # MLmax = MRmax = MLsum = MRsum = nums[midIdx] # for i in range(midIdx): # MLsum += nums[midIdx-i-1] # MLmax = max(MLsum,MLmax) # for i in range(len(nums)-midIdx-1): # MRsum += nums[midIdx+i+1] # MRmax = max(MRsum,MRmax) # Mmax = MLmax + MRmax - nums[midIdx] # return max(Mmax,max(Lmax,Rmax)) # V1.3.1 分治法,写法优化1、2、3 #时间复杂度:O(nlogn) n是数组长度 #空间复杂度:O(logn) 因为调用栈的深度最多是logn # def maxSubArray(nums: List[int]) -> int: # if len(nums) == 1: # return nums[0] # elif len(nums) == 2: # return max(nums[0]+nums[1],nums[0],nums[1]) #1 # midIdx = (len(nums))//2 # Lmax = maxSubArray(nums[:midIdx]) # Rmax = maxSubArray(nums[midIdx+1:]) # MLmax = MRmax = MLsum = MRsum = 0 #2 注意这里要把MLmax、MRmax初值赋0而不是-sys.maxsize:比如右边全是负数,赋0则比较完后,MRmax仍为0,即右边一个数都不取;否则,比较完后MRmax会变成[midIdx+1]的负数,结果出错; # for i in reversed(range(midIdx)): #3 reversed # MLsum += nums[i] # MLmax = max(MLsum,MLmax) # for i in range(midIdx+1,len(nums)): # MRsum += nums[i] # MRmax = max(MRsum,MRmax) # Mmax = MLmax + MRmax + nums[midIdx] #2 # return max(Mmax,Lmax,Rmax) #1 # V1.3.1 动态规划 #时间复杂度:O(n) n是数组长度 #空间复杂度:O(1) ''' 解题思路: dp[i] 表示到当前位置i(以i为结束index)的最大子序列和 状态转移方程为:dp[i] = max(dp[i-1] + nums[i], nums[i]) ''' def maxSubArray(nums: List[int]) -> int: currIdxEndMaxSum = maxSum = nums[0] for i in range(1,len(nums)): currIdxEndMaxSum = max(currIdxEndMaxSum + nums[i], nums[i]) maxSum = max(currIdxEndMaxSum, maxSum) return(maxSum) #--------testcase output--------- print(maxSubArray(nums1)) print(maxSubArray(nums2)) print(maxSubArray(nums3)) print(maxSubArray(nums4)) print(maxSubArray(nums5)) print(maxSubArray(nums6))

     

    Processed: 0.009, SQL: 9