LC 862. Shortest Subarray with Sum at Least K
https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/
这题我最开始也想到了使用双指针,但是始终没有观察到数据规律,所以最终作罢。先说说最优的解法,然后在写我最开始的解法。
对于数组A[0..n-1]. 我们定义B[i] = sum(A[0..i-1])的话,那么sum(A[i..j+1]) = B[j] - B[i]. 如果我们遍历数组A的时候,如果发现(B[j] - B[i])>=K的话,我们在使用B[i]之后,其实我们就可以立刻舍弃B[i]了。 因为对于后面的j'来说, (j'-i)>(j-i). 我们可以将B维护成为一个最小堆,那么这种解法时间复杂度是O(nlgn).
class Solution: def shortestSubarray(self, A: List[int], K: int) -> int: hp = [] hp.append((0, -1)) import heapq acc = 0 n = len(A) ans = n + 1 for i in range(n): x = A[i] acc += x while hp and (acc - hp[0][0]) >= K: (_, j) = heapq.heappop(hp) ans = min(ans, i - j) heapq.heappush(hp, (acc, i)) if ans == (n + 1): ans = -1 return ans
但是如果把B维护成为一个有序数组的话,那么这个时间复杂度还可以降低为O(n). B的顺序是这样的(x, i),x是从低到高,而i也是从低到高。
class Solution: def shortestSubarray(self, A: List[int], K: int) -> int: from collections import deque dq = deque() dq.append((0, -1)) n = len(A) ans = n + 1 acc = 0 for i in range(n): acc += A[i] while dq and (acc - dq[0][0]) >= K: ans = min(ans, i - dq[0][1]) dq.popleft() while dq and acc <= dq[-1][0]: dq.pop() dq.append((acc, i)) if ans == (n + 1): ans = -1 return ans
没有使用双指针,我考虑使用二分搜索:“假设最大长度sz的连续串,是否有可能和是>=K”的。为了能够计算到, 最大长度sz的连续串的最大和,还需要使用一个“循环”最小堆。所以最终时间复杂度是O(n * lgn * lgn) 因为要自己手写一个最小堆,所以代码量就上去了。
class Heap: def __init__(self, n): sz = 1 while sz < n: sz = sz * 2 self.sz = sz self.data = [(1 << 30)] * (2 * sz) def update(self, i, v): p = i + self.sz self.data[p] = v p = p // 2 while p >= 1: x, y = 2 * p, 2 * p + 1 self.data[p] = min(self.data[x], self.data[y]) p = p // 2 def top(self): return self.data[1] class Solution: def shortestSubarray(self, A: List[int], K: int) -> int: def test(sz): heap = Heap(sz) acc = 0 ans = 0 for i in range(len(A)): # 这个性质非常好,每次只需要更新就行 heap.update(i % sz, acc) acc += A[i] ans = max(ans, acc - heap.top()) return ans >= K, ans s, e = 1, len(A) while s <= e: # print(s, e) sz = (s + e) // 2 ok, ans = test(sz) # print(sz, ans, ok) if ok: e = sz - 1 else: s = sz + 1 ans = s if ans == (len(A) + 1): ans = -1 return ans