1. 程式人生 > >Lintcode 最大子陣列 系列問題

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,和這個問題是一類問題。