【leetcode】1031 maximum sum of two non overlapping subarrays

题目

https://leetcode.com/problems/maximum-sum-of-two-non-overlapping-subarrays
给定一个数组A,找到其中不相重合的长为M及L的连续子序列,使两个子序列和最大,返回最大和即可

代码

v1.0

  • 思路(暴力搜索可以想到的优化点):
    • 计算出前后向长为n的子序列内max_m, max_l,然后便利找一下前向+后项一起啥时候最大
    • 优化点1:存一个summary数组,以查表代替重复计算的区间和
    • 优化点2:前向区间里长为M、L的数组和最大是多少,计算一次保存下来,避免重复查表
  • 代码
import collections

class Solution(object):
    
    def calc_summary_value_list(self, A):
        summary_value = []
        tmp_sum = 0
        n = len(A)
        for i in range(n):
            tmp_sum += A[i]
            summary_value.append(tmp_sum)
        return summary_value
    
    def calc_max_n_summary(self, A, L, M, summary_dict):
        # surpose M<L
        n = len(A)
        left_index = M-1
        max_n_dict = collections.defaultdict(dict)
        max_M, max_L = -1, -1
        while(left_index < n):
            right_index_m = left_index-M+1
            right_index_l = left_index-L+1
            tmp_L, tmp_M = -1,-1
            if(right_index_l>=0):
                tmp_L = summary_dict[left_index] - summary_dict[right_index_l] + A[right_index_l]
            if(right_index_m>=0):
                tmp_M = summary_dict[left_index] - summary_dict[right_index_m] + A[right_index_m]
            if tmp_L > max_L:
                max_L = tmp_L
            if tmp_M > max_M:
                max_M = tmp_M
            max_n_dict[left_index] = {'M': max_M, 'L':max_L}
            #print("left_index:%d: %d, %d"%(left_index, max_M, max_L))
            left_index += 1
        return max_n_dict
            
    
    def maxSumTwoNoOverlap(self, A, L, M):
        """
        :type A: List[int]
        :type L: int
        :type M: int
        :rtype: int
        """
        if L<M:
            tmp = M
            M = L
            L = tmp
        n = len(A)
        summary_value = self.calc_summary_value_list(A)
        #print(summary_value)
        pre_order_max_n = self.calc_max_n_summary(A, L, M, summary_value)
        A.reverse()
        summary_value = self.calc_summary_value_list(A)
        post_order_max_n = self.calc_max_n_summary(A, L, M, summary_value)
        max_res = -1
        for i in range(n):
            pre_index = i
            post_index = n-(i+1)-1
            if pre_index < M-1 or post_index<M-1:
                continue
            tmp_res = max(pre_order_max_n[pre_index]['M'] + post_order_max_n[post_index]['L'], pre_order_max_n[pre_index]['L'] + post_order_max_n[post_index]['M'])
            if tmp_res > max_res:
                max_res = tmp_res
        return max_res
  • 踩的bug
    • [i, j]区间和公式计算错误:应为summary_value[j] - summary_value[i] + A[i]
    • 知道前后向区间内max_l, max_m后,计算整个数组max_m, max_l公式错误(区间边缘元素重复);应为pre_index = i, post_index = n-(i+1) -1
    • 计算区间内max_m, max_l时,计算起始下标有误:应为:left_index > M-1(此时区间长度未达L,因此不存在max_l但是有max_m)而非left_index > L-1
  • 借鉴的优化点
    • /捂脸,其实只要算一下前向的就好了,直接扩到N,不用分前后向再拼起来,MG

v1.1

-代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值