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

扫描二维码关注公众号,回复: 3957691 查看本文章

挑战
时间复杂度为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,和这个问题是一类问题。

猜你喜欢

转载自blog.csdn.net/Bismarckczy/article/details/82577187
今日推荐