Open In App

Divide a sorted array in K parts with sum of difference of max and min minimized in each part – Set 2

Improve
Improve
Like Article
Like
Save
Share
Report

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 = 20

Input:  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>


Output

20

Time Complexity: O(N*log(M)), where M is the maximum value of the array.
Auxiliary Space: O(1)

 



Last Updated : 18 Jan, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads