Split Array Largest Sum in JavaAn array numArr[] is given, which only contains the non-negative integers, and an integer sp is also provided. The task is to partition the array into sp continuous subarrays such that the largest sum among these sp subarrays is minimum. Note that subarrays can never be empty. The constraint for this problem is that the size of the input array numArr[] can not be greater than 1000, and the minimum value of sp is 1. For example, for an array numArr[] = {a1, a2, a3, a4, a5, a6} and sp = 2. Then, we can do the split or partition in the 5 ways. Observe the following diagram. In each partition, we have created two subarrays. Suppose in the first partition, the sum of g2 (elements present in g2) is the maximum among g1 and g2. Also, suppose the sum of g4 is the maximum in the second partition, the sum of g6 is the maximum in the third partition, the sum of g8 is the maximum in the fourth partition, and the sum of g10 is the maximum in the fifth partition. Now we will find the minimum of (sum of g2, sum of g4, sum of g6, sum of g8, sum of g10). Suppose the sum of g4 is minimum, then we have to split our array as the second partition (as shown in the diagram), and the sum of g4 will be our answer. Example 1:Input: numArr[] = [2, 7, 10, 5, 8, 9, 4], sp = 2 Output: 24 Explanation: Let's see how we can partition the given input array. Partition 1: g1 = {2}, g2 = {7, 10, 5, 8, 9, 4} Sum of g1 = 2, and sum of g2 = 43 Maximum of (sum of g1, sum of g2) = 43 Partition 2: g1 = {2, 7}, g2 = {10, 5, 8, 9, 4} Sum of g3 = 9, and sum of g4 = 36 Maximum of (sum of g3, sum of g4) = 36 Partition 3: g1 = {2, 7, 10}, g2 = {5, 8, 9, 4} Sum of g5 = 19, and sum of g6 = 26 Maximum of (sum of g5, sum of g6) = 26 Partition 4: g1 = {2, 7, 10, 5}, g2 = {8, 9, 4} Sum of g7 = 24, and sum of g8 = 21 Maximum of (sum of g7, sum of g8) = 24 Partition 5: g1 = {2, 7, 10, 5, 8}, g2 = {9, 4} Sum of g9 = 32, and sum of g10 = 13 Maximum of (sum of g9, sum of g10) = 32 Partition 6: g1 = {2, 7, 10, 5, 8, 9}, g2 = {4} Sum of g11 = 41, and sum of g12 = 4 Maximum of (sum of g11, sum of g12) = 41 Now, the minimum of (43, 36, 26, 24, 32, 41) = 24. The number 24 comes from partition 4. Hence, we need to use partition 4 to get the minimum among the largest sum of the subarrays. Example 2:Input: numArr[] = [8, 3, 9, 2], sp = 4 Output: 9 Explanation: Let's see how we can partition the given input array Partition: g1 = {8}, g2 = {3}, g3 = {9}, g4 = {2}. No other parition is possible In this partition, maximum of (sum of g1, sum of g2 of sum g3, sum of g4) is 9. Hence, our answer is 9. Example 3:Input: numArr[] = [8, 3, 9, 2, 9, 6, 9, 0], sp = 10 Output: Invalid input Explanation: The total number of elements present in the numArr[] is 8, and the value of sp is 10. The maximum number of subarrays that can be created using 8 elements is 8 (each subarray containing 1 element). Therefore, if we try to create 10 subarrays (value of sp is 10), then atleast 2 subarrays have to remain empty. It is already mentioned above, those subarrays derived from the input array can never be empty. Hence, the input is invalid. Approach: Using Dynamic ProgrammingStep 1: The approach is to use a prefixSum array that computes the sum of elements. It is required because whenever we hit the base case (where the subarray required is only one, then it is required to compute the sum of all of the remaining elements, in that case, we want the answer in O(1) time). Thus, the first step is to fill the prefixSum[] array. Step 2: Begin with the index currentIndex as 0 and the number of subarrays subArrCount as sp. It shows the subarray within the range [0, size - 1] and sp subarrays. Step 3: Select those elements that will be part of the current subarray by traversing over the indices beginning from the currentIndex to size - subArrCount. At every index:
Return minLargestSplitSum in order to avoid the repeat computations, also keep it in a memoization table memoArr[] corresponding to the currentIndex and subArrCount. ImplementationObserve the following implementation that is done on the basis of the algorithm explained above. FileName: SplitArrLargestNum.java Output: For the given array: 2 7 10 5 8 9 4 The minimum largest sum for the 2 subarrays is: 24. For the given array: 8 3 9 2 The minimum largest sum for the 4 subarrays is: 9. For the given array: 8 3 9 2 9 6 9 0 Partition for creating 10 subarrays is not possible. Complexity Analysis: In the above program, we have covered almost N * M states with the help of recursion. Also, we have used a for loop that runs from the currentIndex, which further adds O(N) time complexity. Thus, the total time complexity of the program is O(N2 * M), where N represents the total number of elements present in the input array and M is the total number of splits or the subarrays that are allowed which is sp in our case. The array memoArr[] is consuming the space of size N * M. Hence, the space complexity of the above program is O(N * M). In the above program, we have used recursion to solve the problem. However, we can also do the same using loops only. Observe the following program. FileName: SplitArrLargestNum1.java Output: For the given array: 2 7 10 5 8 9 4 The minimum largest sum for the 2 subarrays is: 24. For the given array: 8 3 9 2 The minimum largest sum for the 4 subarrays is: 9. For the given array: 8 3 9 2 9 6 9 0 Partition for creating 10 subarrays is not possible. Complexity Analysis: The complexity of the above program is the same as the previous program. The complexity of the program can be reduced further with the help of binary search. Approach: Using Binary SearchStep 1: Compute the sum of the elements present in the input array numArr[]. Store it in a variable called sumArr (one can also use the name of one's choice) Step 2: Find out the element in the array numArr[], which is of maximum value. Store it in a variable, which is maxEle in our case. Step 3: Fix the search space of the binary search using maxEle and sumVar, where maxEle will serve as the left boundary and sumArr will search as the right boundary. Step 4: Start the binary search using a loop, where the terminating condition will be: when the left boundary is less than the right boundary. Step 5: Find the middle value and treat it as the largest sum allowed for the subarrays. Keep it in a variable, which is the maximumSumAllowed. Step 6: Compute the least number of subarrays whose sum is equal to maximumSumAllowed. Step 7: Check whether the number of subarrays (found in step 6) is greater than, less than, or equal to sp or not. If the count of subarrays is less than or equal to sp, then reduce the value of the right boundary, and assign the value maximumSumAllowed to the answer. If the count of subarrays is more than sp, then increase the value of the left boundary. Step 8: Return the answer. ImplementationLet's see the implementation of the above algorithm. FileName: SplitArrLargestNum2.java Output: For the given array: 2 7 10 5 8 9 4 The minimum largest sum for the 2 subarrays is: 24. For the given array: 8 3 9 2 The minimum largest sum for the 4 subarrays is: 9. For the given array: 8 3 9 2 9 6 9 0 Partition for creating 10 subarrays is not possible. Complexity Analysis: The method minSubArrReq() uses a loop that iterates over each element of the input array. Thus, making the time complexity of O(n). The binary search used in the program uses O(log(s)) time. Thus, the overall time complexity of the program is O(n * log(s)), where n is the total number of elements present in the array, and s is the total sum of elements present in the array. The program is not consuming any extra space (no data structure is used in the program). Hence, the space complexity of the program is constant, i.e., O(1). |