def search_k(arr, k): """ Finds the subarray whose sum is closest to k. If multiple such subarrays exist, there is no guarantee on which one is returned. Time complexity is O(n\log n). Space complexity is O(n). :param arr: list[num] :param k: num :return: tuple[int,int] """ n = len(arr) assert n > 0 a = sorted(enumerate(stated_map(add, arr, 0, prefix=True)), key=snd) # (i, sum(arr[:i])), i in [0, n] left, right = None, None d_min = inf for i, x in a: js = set() # 12 unique indices at most for y in ( x - k, x + k ): # both +k & -k are attempted as k may be positive or negative j = bin_search_left(a, y, key=snd) js.update( (j - 1, j, j + 1)) # bound on the left, on the insertion point, on the right j = bin_search_right(a, y, key=snd) # considers duplicated values js.update((j - 1, j, j + 1)) for jy in [a[j] for j in js if 0 <= j <= n if i != a[j][0] ]: # j-1 may underflow, j and j+1 may overflow p, q = sorted(((i, x), jy)) # tuple sorts lexicographically diff = abs(q[1] - p[1] - k) if diff < d_min: left, right, d_min = p[0], q[0], diff return left, right
def search_k(arr, k): """ Finds the subarray whose sum is closest to k. If multiple such subarrays exist, there is no guarantee on which one is returned. Time complexity is O(n\log n). Space complexity is O(n). :param arr: list[num] :param k: num :return: tuple[int,int] """ n = len(arr) assert n > 0 a = sorted(enumerate(stated_map(add, arr, 0, prefix=True)), key=snd) # (i, sum(arr[:i])), i in [0, n] left, right = None, None d_min = inf for i, x in a: js = set() # 12 unique indices at most for y in (x - k, x + k): # both +k & -k are attempted as k may be positive or negative j = bin_search_left(a, y, key=snd) js.update((j - 1, j, j + 1)) # bound on the left, on the insertion point, on the right j = bin_search_right(a, y, key=snd) # considers duplicated values js.update((j - 1, j, j + 1)) for jy in [a[j] for j in js if 0 <= j <= n if i != a[j][0]]: # j-1 may underflow, j and j+1 may overflow p, q = sorted(((i, x), jy)) # tuple sorts lexicographically diff = abs(q[1] - p[1] - k) if diff < d_min: left, right, d_min = p[0], q[0], diff return left, right
def search(arr): """ Finds the subarray whose sum is closest to 0. If multiple such subarrays exist, returns the first one. :param arr: list[num] :return: tuple[int,int] """ assert len(arr) > 0 a = list(enumerate(stated_map(add, arr, 0, prefix=True))) # (i, sum(arr[:i])), i in [0, n] a.sort(key=snd) # stable sort x, y = min(sliding_window(a, 2), key=lambda z: abs(z[0][1] - z[1][1])) left, right = sorted((x[0], y[0])) return left, right
def search(arr): """ Returns the maximum j – i, where arr[i] <= arr[j]. Time complexity is O(n). Space complexity is O(n). :param arr: list[T], where T is comparable :return: int, non-negative """ assert len(arr) > 0 left_min = list(stated_map(min, arr, arr[0])) right_max = list(stated_map(max, reversed(arr), arr[-1])) right_max.reverse() # since left_min[i] and right_max[i] are both inclusive for i, left_min[i] <= right_max[i] i, j = 0, 0 # two moving boundaries, where i <= j max_dist = 0 while j < len(arr): assert i <= j if left_min[i] <= right_max[j]: max_dist = max(max_dist, j - i) j += 1 else: i += 1 # if arr is monotonously decreasing, then i and j increase alternatively return max_dist
def search(arr): """ Finds the subarray whose sum is closest to 0. If multiple such subarrays exist, returns the first one. :param arr: list[num] :return: tuple[int,int] """ assert len(arr) > 0 a = list(enumerate(stated_map( add, arr, 0, prefix=True))) # (i, sum(arr[:i])), i in [0, n] a.sort(key=snd) # stable sort x, y = min(sliding_window(a, 2), key=lambda z: abs(z[0][1] - z[1][1])) left, right = sorted((x[0], y[0])) return left, right
def search(hist): """ Returns the total volume reservoir above a given histogram. Time complexity is O(n). Space complexity is O(n). :param hist: list[int], non-negative :return: int, non-negative """ n = len(hist) if n < 3: return 0 suffix_max = list(stated_map(max, reversed(hist), hist[-1])) # inclusive suffix max suffix_max.reverse() # suffix_max[0] and suffix_max[-1] will never be accessed vol = 0 # global sum of reservoir volume m = hist[0] # inclusive prefix max for i in range(1, n-1): # hist[0] and hist[-1] can never be a valley m = max(m, hist[i]) cap = min(m, suffix_max[i]) if cap > hist[i]: vol += cap - hist[i] return vol
def search(arr): """ Kadane's algorithm of finding the subarray with the maximum sum. Observation: 1. A max-sum subarray must start & finish with a positive number. 2. It is safe to discard a subarray with a non-positive sum. Time complexity is O(n). Space complexity is O(1). Problem from Jon Bentley's Programming Pearls: If all elements are real numbers uniformly distributed in range [-1, 1], what is the expectation of this maximum sum as a function of size? Empirical evidence seems to suggest a log-log linear relationship: size=31, Ex=3.299060207545906 size=100, Ex=7.011417260111707 size=316, Ex=12.101707427755215 size=1000, Ex=22.20458485964562 size=3162, Ex=40.07622280167929 size=10000, Ex=72.16213987203754 :param arr: list[num] :return: num """ max_sum = max(stated_map(lambda x, s: x + s if x + s > 0 else 0, arr, 0)) if max_sum > 0: return max_sum return max(arr) # if all elements are non-positive
def convert(s, n): def coord(x): sec, rem = divmod(x, sec_size) if rem < n: return 2 * sec, rem return 2 * sec + 1, sec_size - rem m = len(s) if n == 0: return '' if n == 1 or n >= m: return s if n == 2: upper = [s[i] for i in range(0, m, 2)] lower = [s[i] for i in range(1, m, 2)] return ''.join(chain(upper, lower)) sec_size = 2 * n - 2 j_width = [0] * n for x in range(max(0, m-sec_size), m): i, j = coord(x) j_width[j] = max(j_width[j], i + 1) # assert all(x > 0 for x in j_width) j_width[0] = j_width[0] // 2 + 1 j_width[-1] = j_width[-1] // 2 + 1 sum_before = list(stated_map(add, j_width, 0, prefix=True)) # assert sum_before[-1] == m r = [None] * m for x in range(m): i, j = coord(x) if j == 0 or j == n - 1: # assert i % 2 == 0 y = sum_before[j] + i / 2 r[int(y)] = s[x] else: y = sum_before[j] + i r[int(y)] = s[x] # assert not any(x is None for x in r) return ''.join(r)
def search(arr: List[int]) -> int: max_sum = max(stated_map(lambda x, s: x + s if x + s > 0 else 0, arr, 0)) if max_sum > 0: return max_sum return max(arr) # if all elements are non-positive