Divide a sorted array in K parts with sum of difference of max and min minimized in each part – Set 2
Given an ascending sorted array arr[] of size N and an integer K, the task is to partition the given array into K non-empty subarrays such that the sum of differences of the maximum and the minimum of each subarray is minimized.
Examples:
Input: arr[] = { 10, 20, 70, 80 }, N = 4, K = 2
Output: 20
Explanation: The given array can be split in the following way
{10, 20} and {70, 80}. The differences are (20 – 10) = 10 and (80 – 70) = 10
The sum = 10 + 10 = 20Input: arr[] = { 5, 10, 50, 70 }, N = 4, K = 3
Output: 5
Explanation: The subarrays are {5, 10}, {50}, {70}
The differences are 10 – 5 = 5, 50 – 50 = 0, 70 – 70 = 0
The sum = 5 + 0 + 0 = 5
Approach: The other approaches are discussed in Set 1 of this article. Here, we are discussing the Binary Search approach.
Space Optimized Approach: The idea is to use binary search in order to find the answer. The answer lies in [ 0, ( arr[N-1] – arr[0]) ]. See the following observation for justification.
- Assuming permission to make as many cuts as possible, the answer would be 0 because each element can form a subarray. Thus the minimum value would be 0.
- Now the other extreme case can be when only one subarray is allowed, In this case, the answer would be (arr[N-1] – arr[0]). These were the two extreme cases and it is guaranteed that the answer would lie in between them.
Follow the steps below to solve the problem:
- Initialize the variable ans as 0 to store the answer.
- Apply binary search with low = 0, and high = arr[N-1] – arr[0].
- For each value of mid, check if a tape of length mid can cover all the holes within K cuts.
- If so then we have arrived at a potential answer. Store the value and check if it is possible to do the same for a smaller length of tape. (make high = mid – 1 )
- If not then find a larger value for mid (low = mid + 1).
Below is the implementation of the above approach.
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; bool isValid(vector< int > arr, int max_cuts, int len) { // Max_cuts is the maximum no. of // allowed cuts. int n = arr.size(); int start = 0; int i = 1; while (i < n) { // Start from covering as many holes // as you can from start. if (arr[i] - arr[start] <= len) { i++; } else { // If an index is reached // from where it's not possible // to accommodate more elements // in the current subarray // then end this subarray // and go further. len = len - (arr[i - 1] - arr[start]); max_cuts--; start = i; i++; } // If at any point you run out // of maximum subarrays or length // then return false because it's // impossible to obtain this // value of mid. if (max_cuts <= 0 || len <= 0) return false ; } // Covered all subarrays within // the sum maximum number of subarrays // so return true. return true ; } // Function to find the minimum sum void findMinTapeLength(vector< int > arr, int N, int K) { // Initialise low and high int high = arr[N - 1] - arr[0], low = 0; int ans = 0; // Apply Binary Search while (low <= high) { int mid = low + (high - low) / 2; // IsValid() function checks if // max value of mid is sufficient // to break the array in K subarrays if (isValid(arr, K, mid)) { // If true then set this as // the current answer and divide // your range to [low, mid-1] // to check for a lower sum ans = mid; high = mid - 1; } // If false then that means need // to increase the current length // so set range to [mid+1, high] else low = mid + 1; } cout << ans; } // Driver Code int main() { vector< int > arr = { 10, 20, 70, 80 }; int N = 4, K = 2; findMinTapeLength(arr, N, K); } // This code is contributed by Samim Hossain Mondal. |
Java
// Java program for the above approach import java.io.*; class GFG { // Function to find the minimum sum static void findMinTapeLength( int [] arr, int N, int K) { // Initialise low and high int high = arr[N - 1 ] - arr[ 0 ], low = 0 ; int ans = 0 ; // Apply Binary Search while (low <= high) { int mid = low + (high - low) / 2 ; // IsValid() function checks if // max value of mid is sufficient // to break the array in K subarrays if (isValid(arr, K, mid)) { // If true then set this as // the current answer and divide // your range to [low, mid-1] // to check for a lower sum ans = mid; high = mid - 1 ; } // If false then that means need // to increase the current length // so set range to [mid+1, high] else low = mid + 1 ; } System.out.println(ans); } static boolean isValid( int [] arr, int max_cuts, int len) { // Max_cuts is the maximum no. of // allowed cuts. int n = arr.length; int start = 0 ; int i = 1 ; while (i < n) { // Start from covering as many holes // as you can from start. if (arr[i] - arr[start] <= len) { i++; } else { // If an index is reached // from where it's not possible // to accommodate more elements // in the current subarray // then end this subarray // and go further. len = len - (arr[i - 1 ] - arr[start]); max_cuts--; start = i; i++; } // If at any point you run out // of maximum subarrays or length // then return false because it's // impossible to obtain this // value of mid. if (max_cuts <= 0 || len <= 0 ) return false ; } // Covered all subarrays within // the sum maximum number of subarrays // so return true. return true ; } // Driver Code public static void main(String[] args) { int [] arr = { 10 , 20 , 70 , 80 }; int N = 4 , K = 2 ; findMinTapeLength(arr, N, K); } } |
Python3
# Python code for the above approach # Function to find the minimum sum def findMinTapeLength(arr, N, K): # Initialise low and high high = arr[N - 1 ] - arr[ 0 ] low = 0 ans = 0 # Apply Binary Search while (low < = high): mid = low + ((high - low) / / 2 ) # IsValid() function checks if # max value of mid is sufficient # to break the array in K subarrays if (isValid(arr, K, mid)): # If true then set this as # the current answer and divide # your range to [low, mid-1] # to check for a lower sum ans = mid high = mid - 1 # If false then that means need # to increase the current length # so set range to [mid+1, high] else : low = mid + 1 print (ans) def isValid(arr, max_cuts, _len): # Max_cuts is the maximum no. of # allowed cuts. n = len (arr) start = 0 i = 1 while (i < n): # Start from covering as many holes # as you can from start. if (arr[i] - arr[start] < = _len): i + = 1 else : # If an index is reached # from where it's not possible # to accommodate more elements # in the current subarray # then end this subarray # and go further. _len = _len - (arr[i - 1 ] - arr[start]) max_cuts - = 1 start = i i + = 1 # If at any point you run out # of maximum subarrays or length # then return false because it's # impossible to obtain this # value of mid. if (max_cuts < = 0 or _len < = 0 ): return False # Covered all subarrays within # the sum maximum number of subarrays # so return true. return True # Driver Code arr = [ 10 , 20 , 70 , 80 ] N = 4 K = 2 findMinTapeLength(arr, N, K) # This code is contributed by gfgking |
C#
// C# program for the above approach using System; class GFG { // Function to find the minimum sum static void findMinTapeLength( int [] arr, int N, int K) { // Initialise low and high int high = arr[N - 1] - arr[0], low = 0; int ans = 0; // Apply Binary Search while (low <= high) { int mid = low + (high - low) / 2; // IsValid() function checks if // max value of mid is sufficient // to break the array in K subarrays if (isValid(arr, K, mid)) { // If true then set this as // the current answer and divide // your range to [low, mid-1] // to check for a lower sum ans = mid; high = mid - 1; } // If false then that means need // to increase the current length // so set range to [mid+1, high] else low = mid + 1; } Console.WriteLine(ans); } static bool isValid( int [] arr, int max_cuts, int len) { // Max_cuts is the maximum no. of // allowed cuts. int n = arr.Length; int start = 0; int i = 1; while (i < n) { // Start from covering as many holes // as you can from start. if (arr[i] - arr[start] <= len) { i++; } else { // If an index is reached // from where it's not possible // to accommodate more elements // in the current subarray // then end this subarray // and go further. len = len - (arr[i - 1] - arr[start]); max_cuts--; start = i; i++; } // If at any point you run out // of maximum subarrays or length // then return false because it's // impossible to obtain this // value of mid. if (max_cuts <= 0 || len <= 0) return false ; } // Covered all subarrays within // the sum maximum number of subarrays // so return true. return true ; } // Driver Code public static void Main() { int [] arr = { 10, 20, 70, 80 }; int N = 4, K = 2; findMinTapeLength(arr, N, K); } } // This code is contributed by Samim Hossain Mondal. |
Javascript
<script> // JavaScript code for the above approach // Function to find the minimum sum function findMinTapeLength(arr, N, K) { // Initialise low and high let high = arr[N - 1] - arr[0], low = 0; let ans = 0; // Apply Binary Search while (low <= high) { let mid = low + Math.floor((high - low) / 2); // IsValid() function checks if // max value of mid is sufficient // to break the array in K subarrays if (isValid(arr, K, mid)) { // If true then set this as // the current answer and divide // your range to [low, mid-1] // to check for a lower sum ans = mid; high = mid - 1; } // If false then that means need // to increase the current length // so set range to [mid+1, high] else low = mid + 1; } document.write(ans); } function isValid(arr, max_cuts, len) { // Max_cuts is the maximum no. of // allowed cuts. let n = arr.length; let start = 0; let i = 1; while (i < n) { // Start from covering as many holes // as you can from start. if (arr[i] - arr[start] <= len) { i++; } else { // If an index is reached // from where it's not possible // to accommodate more elements // in the current subarray // then end this subarray // and go further. len = len - (arr[i - 1] - arr[start]); max_cuts--; start = i; i++; } // If at any point you run out // of maximum subarrays or length // then return false because it's // impossible to obtain this // value of mid. if (max_cuts <= 0 || len <= 0) return false ; } // Covered all subarrays within // the sum maximum number of subarrays // so return true. return true ; } // Driver Code let arr = [10, 20, 70, 80]; let N = 4, K = 2; findMinTapeLength(arr, N, K); // This code is contributed by Potta Lokesh </script> |
20
Time Complexity: O(N*log(M)), where M is the maximum value of the array.
Auxiliary Space: O(1)
Please Login to comment...