Space-efficient algorithm for finding the largest balanced subarray?

后端 未结 10 1170
谎友^
谎友^ 2020-12-22 22:54

given an array of 0s and 1s, find maximum subarray such that number of zeros and 1s are equal. This needs to be done in O(n) time and O(1) space.

I have an algo whic

10条回答
  •  一整个雨季
    2020-12-22 23:44

    Like Neil, I find it useful to consider the alphabet {±1} instead of {0, 1}. Assume without loss of generality that there are at least as many +1s as -1s. The following algorithm, which uses O(sqrt(n log n)) bits and runs in time O(n), is due to "A.F."

    Note: this solution does not cheat by assuming the input is modifiable and/or has wasted bits. As of this edit, this solution is the only one posted that is both O(n) time and o(n) space.

    A easier version, which uses O(n) bits, streams the array of prefix sums and marks the first occurrence of each value. It then scans backward, considering for each height between 0 and sum(arr) the maximal subarray at that height. Some thought reveals that the optimum is among these (remember the assumption). In Python:

    sum = 0
    min_so_far = 0
    max_so_far = 0
    is_first = [True] * (1 + len(arr))
    for i, x in enumerate(arr):
        sum += x
        if sum < min_so_far:
            min_so_far = sum
        elif sum > max_so_far:
            max_so_far = sum
        else:
            is_first[1 + i] = False
    
    sum_i = 0
    i = 0
    while sum_i != sum:
        sum_i += arr[i]
        i += 1
    sum_j = sum
    j = len(arr)
    longest = j - i
    for h in xrange(sum - 1, -1, -1):
        while sum_i != h or not is_first[i]:
            i -= 1
            sum_i -= arr[i]
        while sum_j != h:
            j -= 1
            sum_j -= arr[j]
        longest = max(longest, j - i)
    

    The trick to get the space down comes from noticing that we're scanning is_first sequentially, albeit in reverse order relative to its construction. Since the loop variables fit in O(log n) bits, we'll compute, instead of is_first, a checkpoint of the loop variables after each O(√(n log n)) steps. This is O(n/√(n log n)) = O(√(n/log n)) checkpoints, for a total of O(√(n log n)) bits. By restarting the loop from a checkpoint, we compute on demand each O(√(n log n))-bit section of is_first.

    (P.S.: it may or may not be my fault that the problem statement asks for O(1) space. I sincerely apologize if it was I who pulled a Fermat and suggested that I had a solution to a problem much harder than I thought it was.)

提交回复
热议问题