How to find the max array from both sides

Question:

Given an integer array A, I need to pick B elements from either left or right end of the array A to get maximum sum. If B = 4, then you can pick the first four elements or the last four elements or one from front and three from back etc.

Example input:

A = [5, -2, 3, 1, 2]
B = 3

The correct answer is 8 (by picking 5 from the left, and 1 and 2 from the right).

My code:

def solve(A, B):
    n = len(A)
    # track left most index and right most index i,j
    i = 0
    j = n-1
    Sum = 0
    B2 = B  # B for looping and B2 for reference it
    # Add element from front
    for k in range(B):
        Sum += A[k]
        
    ans = Sum
    # Add element from last
    for _ in range(B2):
       # Remove element from front
       Sum -= A[i]
       # Add element from last
       Sum += A[j]
       ans = max(ans, Sum)

    return ans

But the answer I get is 6.

Asked By: Maws

||

Answers:

Solution based on sum of the left and right slices:

Data = [-533, -666, -500, 169, 724, 478, 358, -38, -536, 705, -855, 281, -173, 961, -509, -5, 942, -173, 436, -609,
        -396, 902, -847, -708, -618, 421, -284, 718, 895, 447, 726, -229, 538, 869, 912, 667, -701, 35, 894, -297, 811,
        322, -667, 673, -336, 141, 711, -747, -132, 547, 644, -338, -243, -963, -141, -277, 741, 529, -222, -684,
        35]  # to avoid var shadowing


def solve(A, B):
    m, ln = None, len(A)
    for i in range(B):
        r = -(B-i-1)  # r is right index to slice
        tmp = sum(A[0:i + 1]) + sum(A[r:]) if r < 0 else 0
        m = tmp if m is None else max(m, tmp)
    return m


print(solve(Data, 48))  # 6253
Answered By: Алексей Р

A recursive approach with comments.


def solve(A, B, start_i=0, end_i=None):

    # set end_i to the index of last element
    if end_i is None:
        end_i = len(A) - 1

    # base case 1: we have no more moves
    if B == 0:
        return 0

    # base case 2: array only has two elemens
    if end_i - start_i == 1:
        return max(A)

    # next, we need to choose whether to use one of our moves on 
    # the left side of the array or the right side. We compute both, 
    # then check which one is better. 
    
    # pick the left side to sum
    sum_left = A[start_i] + solve(A, B - 1, start_i + 1, end_i)

    # pick the right side to sum
    sum_right = A[end_i] + solve(A, B - 1, start_i, end_i - 1)

    # return the max of both options
    return max(sum_left, sum_right)

arr = [5, -2, 3, 1, 2]
print(solve(arr, 3)) # prints 8
Answered By: travisjayday

Solution

def max_bookend_sum(x, n):
    bookends = x[-n:] + x[:n]
    return max(sum(bookends[i : i + n]) for i in range(n + 1))

Explanation

Let n = 3 and take x,

>>> x = [4, 9, -7, 4, 0, 4, -9, -8, -6, 9]

Grab the "right" n elements, concatenate with the "left" n:

>>> bookends = x[-n:] + x[:n]
>>> bookends  # last three elements from x, then first three
[-8, -6, 9, 4, 9, -7]

Take "sliding window" groups of n elements:

>>> [bookends[i : i + n] for i in range(n + 1)]
[[-8, -6, 9], [-6, 9, 4], [9, 4, 9], [4, 9, -7]]

Now, instead of producing the sublists sum them instead, and take the max:

>>>  max(sum(bookends[i : i + n]) for i in range(n + 1))
22

For your large array A from the comments:

>>> max(sum(bookends[i : i + n]) for i in range(n + 1))
6253
Answered By: ddejohn

The idea is if we have this list:

[5, 1, 1, 8, 2, 10, -2]

Then the possible numbers for B=3 would be:

lhs = [5,  1,  1]  # namely L[+0], L[+1], L[+2]
rhs = [2, 10, -2]  # namely R[-3], R[-2], R[-1]

The possible combinations would be:

[5,  1,  1]  # L[+0], L[+1], L[+2]
[5,  1, -2]  # L[+0], L[+1], R[-1]
[5, 10, -2]  # L[+0], R[-2], R[-1]
[2, 10, -2]  # R[-3], R[-2], R[-1]

As you can see, we can easily perform forward and backward iterations which will start from all L (L[+0], L[+1], L[+2]), and then iteratively replacing the last element with an R (R[-1], then R[-2], then R[-3]) up until all are R (R[-3], then R[-2], then R[-1]).

def solve(A, B):
    n = len(A)
    max_sum = None
    for lhs, rhs in zip(range(B, -1, -1), range(0, -(B+1), -1)):
        combined = A[0:lhs] + (A[rhs:] if rhs < 0 else [])
        combined_sum = sum(combined)
        max_sum = combined_sum if max_sum is None else max(max_sum, combined_sum)
    return max_sum

for A in [
    [5, 1, 1, 8, 2, 10, -2],
    [5, 6, 1, 8, 2, 10, -2],
    [5, 6, 3, 8, 2, 10, -2],
]:
    print(A)
    print("t1 =", solve(A, 1))
    print("t2 =", solve(A, 2))
    print("t3 =", solve(A, 3))
    print("t4 =", solve(A, 4))

Output

[5, 1, 1, 8, 2, 10, -2]
    1 = 5
    2 = 8
    3 = 13
    4 = 18
[5, 6, 1, 8, 2, 10, -2]
    1 = 5
    2 = 11
    3 = 13
    4 = 20
[5, 6, 3, 8, 2, 10, -2]
    1 = 5
    2 = 11
    3 = 14
    4 = 22
public int solve(int[] A, int B) {
    int sum = 0;
    int i = 0;
    int n = A.length -1;
    for (int k = 0; k < B; k++){
        sum += A[k];
    }
    int ans = sum;
    int B2 = B -1;
    for (int j = n; j > n -B; j--){
        sum -= A[B2];
        sum += A[j];
        ans = Math.max(ans, sum);
        B2--;
    }
    return ans;
}

}

Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.