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++ 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 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);
}
} |
# 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# 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. |
<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)