Lintcode 最大子陣列 系列問題
問題1,最大子陣列
給定一個整數陣列,找到一個具有最大和的子陣列,返回其最大和。
樣例
給出陣列[−2,2,−3,4,−1,2,1,−5,3],符合要求的子陣列為[4,−1,2,1],其最大和為6
挑戰
要求時間複雜度為O(n)
def max_sub(nums):
current_sum=0
total_sum=num[0]
for num in nums:
current_sum=max(current_sum+num,num)
total_sum=max(current_sum,total_sum)
return total_sum
思路:
用current_sum儲存好每一步的和,如果current_sum是正數,就會保留之前的current_sum,如果是負數,會從下一個num重新計數。
用total_sum和current_sum的區別是,total_sum決定是否加入當前的新元素,而current_sum決定是否儲存之前的元素和。
問題2 最小子陣列
給定一個整數陣列,找到一個具有最小和的子陣列。返回其最小和。
樣例
給出陣列[1, -1, -2, 1],返回 -3
def minSubArray(nums):
# write your code here
current=0
total=nums[0]
for num in nums:
current=min(current+num,num)
total=min(current,total)
print(total)
return total
思路:
跟求最大子陣列的思路是一樣的。
問題3,最大子陣列 II
給定一個整數陣列,找出兩個 不重疊 子陣列使得它們的和最大。
每個子陣列的數字在陣列中的位置應該是連續的。
返回最大的和。
樣例
給出陣列 [1, 3, -1, 2, -1, 2]
這兩個子陣列分別為 [1, 3] 和 [2, -1, 2] 或者 [1, 3, -1, 2] 和 [2],它們的最大和都是 7
挑戰
要求時間複雜度為 O(n)
def maxTwoSubArrays(nums):
# write your code here
n=len(nums)
total_left=nums[0]
current_left=0
left_sum_array=[0]*n
for i in range(n):
current_left=max(current_left+nums[i],nums[i])
total_left=max(current_left,total_left)
left_sum_array[i]=total_left
# print('left',total_left)
total_right=nums[n-1]
current_right=0
right_sum_array=[0]*n
for i in range(n-1,-1,-1):
current_right=max(current_right+nums[i],nums[i])
total_right=max(current_right,total_right)
right_sum_array[i]=total_right
# print('right',total_right)
final_sum=-100000
for i in range(n-1):
final_sum=max(final_sum,right_sum_array[i+1]+left_sum_array[i])
# (0)>>>(i) | (i+1)<<<(n-1)
# print(final_sum)
return final_sum
思路:
題目要求是兩個不重疊子陣列的和最大
我用一個left陣列表達從第0個元素到第i個元素中,隨i變化的最大陣列和,這就是之前問題1的解法;同理,用一個right陣列表達從右往左第n-1個元素到第i個元素,隨i變化的最大陣列和。
然後以i為分界線,使得i取0~n-1,來找兩個子陣列最大的和,過程是這樣的
# (0)>>>(i) | (i+1)<<<(n-1)
問題4 最大子陣列差
給定一個整數陣列,找出兩個不重疊的子陣列A和B,使兩個子陣列和的差的絕對值|SUM(A) - SUM(B)|最大。
返回這個最大的差值。
樣例
給出陣列[1, 2, -3, 1],返回 6
挑戰
時間複雜度為O(n),空間複雜度為O(n)
class Solution:
"""
@param nums: A list of integers
@return: An integer indicate the value of maximum difference between two substrings
"""
def maxDiffSubArrays(self, nums):
# write your code here
n=len(nums)
current_left_max,current_left_min=0,0
total_left_max,total_left_min=nums[0],nums[0]
save_left_max,save_left_min=[0]*n,[0]*n
for i in range(n):
current_left_max=max(current_left_max+nums[i],nums[i])
total_left_max=max(current_left_max,total_left_max)
save_left_max[i]=total_left_max
# print('total_left_max',total_left_max)
current_left_min=min(current_left_min+nums[i],nums[i])
total_left_min=min(current_left_min,total_left_min)
save_left_min[i]=total_left_min
# print('total_left_min',total_left_min)
current_right_min,current_right_max=0,0
total_right_min,total_right_max=nums[n-1],nums[n-1]
save_right_min,save_right_max=[0]*n,[0]*n
for i in range(n-1,-1,-1):
current_right_max=max(current_right_max+nums[i],nums[i])
total_right_max=max(total_right_max,current_right_max)
save_right_max[i]=total_right_max
# print('total_right_max',total_right_max)
current_right_min=min(current_right_min+nums[i],nums[i])
total_right_min=min(total_right_min,current_right_min)
save_right_min[i]=total_right_min
# print('total_right_min',total_right_min)
final_diff=-100000
for i in range(n-1):
final_diff=max(final_diff,abs(save_right_max[i+1]-save_left_min[i]),abs(save_left_max[i]-save_right_min[i+1]))
# print(final_diff)
return final_diff
思路,如果已經刷過了之前的幾道題,那麼這題就很簡單了,找到四個陣列,分別是,左到右最大子陣列,左到右最小子陣列;右到左最大子陣列,右到左最小子陣列。將他們大減小來來比較,進而找到最大子陣列差。
下個部落格講best time to buy and sell stocks,和這個問題是一類問題。