Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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
Example #9
0
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)
Example #10
0
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