1477. 找两个和为目标值且不重叠的子数组

思路

(由于测试用例不完全)周赛时AC了,但是实际代码是有问题的 说一下我的思路吧:

代码(WA)

python3

class Solution:
    def minSumOfLengths(self, arr: List[int], target: int) -> int:
      presum = [0] * len(arr)
      temp = 0
      for i in range(len(arr)):
        presum[i] = temp + arr[i]
        temp += arr[i]
      presum = [0] + presum
      
      j = 0
      k = 1
      queue = []
      while j < len(presum) and k < len(presum):
        if presum[k] - presum[j] == target:
          if len(queue) > 0:
            # print(queue[-1], [j,k])
            if queue[-1][1] > j:
              if (queue[-1][1] - queue[-1][0]) > (k - j):
                queue.pop()
                queue.append([j,k])
            else:
              queue.append([j,k])
          else:
            queue.append([j,k])
          j += 1
        elif presum[k] - presum[j] < target:
          k += 1
        else:
          j += 1
      if len(queue) < 2:
        return -1
      else:
        sq = sorted([x[1]-x[0] for x in queue])
        return sq[0] + sq[1]
问题

上面的思路有一个漏洞,我是在遍历的过程中,遇到了相交的字串,就直接把之前的字串pop掉了。这明显是错误的。

如:[[1,5], [3,6], [5,7] 这种情况,当我的到[3,6]这一组的时候,我发现和[1,5]相交了,我就直接把[1,5],去掉了。实际[1,5][5,7]不相交,所以这种做法是有问题的

改进代码

先记录所有和为target的字串,然后在遍历比较

尝试改一下代码,TLE!

代码(TLE)

python3

class Solution:
    def minSumOfLengths(self, arr: List[int], target: int) -> int:
      presum = [0] * len(arr)
      temp = 0
      for i in range(len(arr)):
        presum[i] = temp + arr[i]
        temp += arr[i]
      presum = [0] + presum
      
      j = 0
      k = 1
      queue = []
      while j < len(presum) and k < len(presum):
        if presum[k] - presum[j] == target:
          if len(queue) > 0:
            queue.append([j,k])
          else:
            queue.append([j,k])
          j += 1
        elif presum[k] - presum[j] < target:
          k += 1
        else:
          j += 1

      r = []
      for i in range(len(queue) - 1):
        for j in range(i, len(queue)):
          if (queue[i][1] <= queue[j][0]):
            r.append((queue[j][1] - queue[j][0]) + (queue[i][1] - queue[i][0]))
      return -1 if len(r) == 0 else min(r)

超时的原因是最后有双for遍历和为target字串的操作,最坏情况\(O(n^2)\),爆炸

改进思路

尝试写一下代码,AC!

代码

python3

class Solution:
  def minSumOfLengths(self, arr: List[int], target: int) -> int:
    min_length = [math.inf] * len(arr)
    presum = 0 #前缀和
    start = 0 #字串的起始下标,end表示字串的结束下标
    cur_min = math.inf #当前见过的最小长度
    result = math.inf
    for end in range(len(arr)):
      presum += arr[end]
      while presum > target:
        presum -= arr[start]
        start += 1
      if presum == target:
        cur_len = end - start + 1
        if end > 0 and min_length[start-1] != math.inf:
          result = min(result, cur_len + min_length[start-1])
        cur_min = min(cur_len, cur_min)
      min_length[end] = min(min_length[end], cur_min)
    return -1 if result == math.inf else result