Max double slice sum

前端 未结 14 1125
后悔当初
后悔当初 2020-12-13 20:53

Recently, I tried to solve the Max Double Slice Sum problem in codility which is a variant of max slice problem. My Solution was to look for a slice that has maximum value w

相关标签:
14条回答
  • 2020-12-13 21:08

    Here is my solution https://github.com/dinkar1708/coding_interview/blob/master/codility/max_slice_problem_max_double_slice_sum.py

    Codility 100% in Python

    def solution(A):
    """
    Idea is use two temporary array and store sum using Kadane’s algorithm
    ending_here_sum[i] -  the maximum sum contiguous sub sequence ending at index i
    starting_here_sum[i] - the maximum sum contiguous sub sequence starting with index i
    
    Double slice sum should be the maximum sum of ending_here_sum[i-1]+starting_here_sum[i+1]
    
    Reference -
    https://rafal.io/posts/codility-max-double-slice-sum.html
    
    The sum of double slice (X, Y, Z) is the total of A[X + 1] + A[X + 2] + ... + A[Y - 1] + A[Y + 1] + A[Y + 2] + ... + A[Z - 1].
    A[0] = 3
    A[1] = 2
    A[2] = 6
    A[3] = -1
    A[4] = 4
    A[5] = 5
    A[6] = -1
    A[7] = 2
    contains the following example double slices:
    double slice (0, 3, 6), sum is 2 + 6 + 4 + 5 = 17,
    double slice (0, 3, 7), sum is 2 + 6 + 4 + 5 - 1 = 16,
    double slice (3, 4, 5), sum is 0.
    """
    ar_len = len(A)
    ending_here_sum = [0] * ar_len
    starting_here_sum = [0] * ar_len
    
    # the maximum sum contiguous sub sequence ending at index i
    for index in range(1, ar_len - 2):  # A[X + 1] + A[X + 2] + ... + A[Y - 1]
        ending_here_sum[index] = max(ending_here_sum[index - 1] + A[index], 0)
    
    # the maximum sum contiguous sub sequence starting with index i
    for index in range(ar_len - 2, 1, -1):  # A[Y + 1] + A[Y + 2] + ... + A[Z - 1]
        starting_here_sum[index] = max(starting_here_sum[index + 1] + A[index], 0)
    
    # Double slice sum should be the maximum sum of ending_here_sum[i-1]+starting_here_sum[i+1]
    max_slice_sum = ending_here_sum[0] + starting_here_sum[2]
    for index in range(1, ar_len - 1):
        max_slice_sum = max(max_slice_sum, ending_here_sum[index - 1] + starting_here_sum[index + 1])
    
    return max_slice_sum
    
    0 讨论(0)
  • 2020-12-13 21:09

    Well, I have my solution, may be not the best one bit 100%/100%, according to codility requierments.

    #include<vector>
    #include<unordered_map>
    #include<algorithm>
    
    using namespace std;
    
    int solution(vector<int> &A) {
        unordered_map<size_t, int> maxSliceLeftToRight;
        maxSliceLeftToRight[1] = 0;
        unordered_map<size_t, int> maxSliceRightToLeft;
        maxSliceRightToLeft[A.size() - 2] = 0;
        int sum = 0;
        for (size_t i = 2; i < A.size() - 1; i++) {
            int tmpSum = max(sum + A[i - 1], 0);
            sum = max(A[i - 1], tmpSum);
            maxSliceLeftToRight[i] = sum;
        }
        sum = 0;
        for (size_t i = A.size() - 3; i > 0; i--) {
            int tmpSum = max(sum + A[i + 1], 0);
            sum = max(A[i + 1], tmpSum);
            maxSliceRightToLeft[i] = sum;
        }
        int maxDoubleSliceSum = 0;
        for (auto & entry : maxSliceLeftToRight) {
            int maxRight = maxSliceRightToLeft[entry.first];
            if (entry.second + maxRight > maxDoubleSliceSum)
                maxDoubleSliceSum = entry.second + maxRight;
        }
        return maxDoubleSliceSum;
    }
    
    0 讨论(0)
  • 2020-12-13 21:10

    Think I got it based on Moxis Solution. Tried to point out the Intension.

        class Solution {
        public int solution(int[] A) { 
    
        int n = A.length - 1;
    
        // Array with cummulated Sums when the first Subarray ends at Index i
        int[] endingAt = new int[A.length];
        int helperSum = 0;
    
        // Optimal Subtotal before all possible Values of Y
        for(int i = 1; i < n; ++i ) {            
            helperSum = Math.max(0, A[i] + helperSum);
            endingAt[i] = helperSum;
        }
    
        // Array with cummulated Sums when the second Subarray starts at Index i
        int[] startingAt = new int[A.length];
        helperSum = 0;
    
        // Optimal Subtotal behind all possible Values of Y
        for(int i = (n - 1); i > 0; --i ) {   
            helperSum = Math.max(0, A[i] + helperSum);
            startingAt[i] = helperSum;
        }
    
        //Searching optimal Y
        int sum = 0;
        for(int i = 0; i < (n - 1); ++i) {
            sum = Math.max(sum, endingAt[i] + startingAt[i+2]);
        }
    
        return sum;
    
    }
    

    }

    0 讨论(0)
  • 2020-12-13 21:11

    Here 100% in python, might not be as elegant as some other solutions above, but considers all possible cases.

    def solution(A):
    #Trivial cases 
     if len(A)<=3:
      return 0 
     idx_min=A.index(min(A[1:len(A)-1]))
     minval=A[idx_min]
     maxval=max(A[1:len(A)-1])
     if maxval<0:
         return 0
     if minval==maxval:
         return minval*(len(A)-3)
    #Regular max slice if all numbers > 0     
     if minval>=0:
      max_ending=0     
      max_slice=0
      for r in range(1,len(A)-1):
            if (r!=idx_min):     
             max_ending=max(0,A[r]+max_ending)
             max_slice = max(max_slice, max_ending)
      return max_slice  
    #Else gets more complicated        
     else :
    #First remove negative numbers at the beginning and at the end 
      idx_neg=1
      while A[idx_neg] <= 0 and idx_neg<len(A) :
       A[idx_neg]=0
       idx_neg+=1
      idx_neg=len(A)-2
      #<0 , 0
      while A[idx_neg] <= 0 and idx_neg > 0 :
       A[idx_neg]=0
       idx_neg-=1
    #Compute partial positive sum from left
    #and store it in Left array   
      Left=[0]*len(A) 
      max_left=0
      for r in range(1,len(A)-1):
          max_left=max(0,A[r]+max_left)
          Left[r]=max_left
    #Compute partial positive sum from right
    #and store it in Right array        
      max_right=0 
      Right=[0]*len(A)      
      for r in range(len(A)-2,0,-1):      
          max_right=max(0,A[r]+max_right)
          Right[r]=max_right   
    #Compute max of Left[r]+Right[r+2].
    #The hole in the middle corresponding
    #to Y index of double slice (X, Y, Z)           
      max_slice=0
      for r in range(1,len(A)-3):
         max_slice=max(max_slice,Left[r]+Right[r+2])   
      return max_slice     
     pass
    
    0 讨论(0)
  • 2020-12-13 21:16

    This is a Java 100/100 Solution: https://codility.com/demo/results/demoVUMMR9-JH3/

    class Solution {
        public int solution(int[] A) {        
            int[] maxStartingHere = new int[A.length];
            int[] maxEndingHere = new int[A.length];
            int maxSum = 0, len = A.length;
    
            for(int i = len - 2; i > 0; --i ) {            
                maxSum = Math.max(0, A[i] + maxSum);
                maxStartingHere[i] = maxSum;
            }
            maxSum = 0;
            for(int i = 1; i < len - 1; ++i ) {            
                maxSum = Math.max(0, A[i] + maxSum);
                maxEndingHere[i] = maxSum;
            }
            int maxDoubleSlice = 0;
    
            for(int i = 0; i < len - 2; ++i) {
                maxDoubleSlice = Math.max(maxDoubleSlice, maxEndingHere[i] + maxStartingHere[i+2]);
            }
    
            return maxDoubleSlice;
    
        }
    }
    

    You can find more information going to this Wikipedia link and in the Programming Pearls book.

    0 讨论(0)
  • 2020-12-13 21:17

    Here is an alternative solution to the proposed by me before, more readable and understandable:

    int solution(vector<int> & A){
    if(A.size() < 4 )
        return 0;
    int maxSum = 0;
    int sumLeft = 0;
    unordered_map<int, int> leftSums;
    leftSums[0] = 0;
    for(int i = 2; i < A.size()-1; i++){
        sumLeft += A[i-1];
        if(sumLeft < 0)
            sumLeft = 0;
        leftSums[i-1] =  sumLeft;
    }
    
    int sumRight = 0;
    unordered_map<int, int> rightSums;
    rightSums[A.size()-1] =  sumRight;
    for( int i = A.size() - 3; i >= 1; i--){
        sumRight += A[i+1];
        if(sumRight < 0)
            sumRight = 0;
        rightSums[i+1] = sumRight;
    }
    
    for(long i = 1; i < A.size() - 1; i++){
        if(leftSums[i-1] + rightSums[i+1] > maxSum)
            maxSum = leftSums[i-1] + rightSums[i+1];
    }
    return maxSum;
    

    }

    0 讨论(0)
提交回复
热议问题