Skip to content
Related Articles
Get the best out of our app
GFG App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Minimum time required to schedule K processes

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

Given a positive integer K and an array arr[] consisting of N positive integers, such that arr[i] is the number of processes ith processor can schedule in 1 second. The task is to minimize the total time required to schedule K processes such that after scheduling by the ith processor, arr[i] is reduced to floor(arr[i]/2).

Examples:

Input: N = 5, arr[] = {3, 1, 7, 2, 4}, K = 15
Output: 4
Explanation:
The order of scheduled process are as follows:

  1. The 3rd process is scheduled first. The array arr[] modifies to {3, 1, 3, 2, 4}, as arr[2] = floor(arr[2] / 2) = floor(7 / 2) = 3.
  2. The 5th process is scheduled next. The array arr[] modifies to {3, 1, 3, 2, 2}.
  3. The 1st process is scheduled next. The array arr[] modifies to {1, 1, 3, 2, 2}.
  4. The 2nd process is scheduled next. The array arr[] modifies to {3, 0, 3, 2, 4}.

The total processes scheduled by all the process = 7 + 4 + 3 + 1 = 15(= K) and the total time required is 4 seconds.

Input: N = 4, arr[] = {1, 5, 8, 6}, K = 10
Output: 2

Naive Approach: The simplest approach to solve the given problem is to sort the given list in ascending order and choose the processor with the highest ability and reduce the value of K by that value and delete that processor from the list and add half of that in the sorted list again. Repeat the above process until at least K processes are scheduled and print the time required after scheduling at least K processes.

Time Complexity: O(N*log N)
Auxiliary Space: O(N)

Efficient Approach: The above approach can also be optimized by using the concept of Hashing. Follow the below steps to solve the problem:

  • Initialize an auxiliary array tmp[] of the size of the maximum element present in the given array.
  • Initialize a variable, say count to store the minimum time to schedule all processes respectively.
  • Traverse the given array tmp[] from the end and perform the following steps:
    • If the current element in tmp[] is greater than 0 and i * tmp[i] is smaller than K.
      • Decrease the value of K by the value i * tmp[i].
      • Increase tmp[i/2] by tmp[i] as the ability of the processor will decrease by half.
      • Increase the value of count by the value tmp[i].
      • If the value of K is already smaller than or equal to 0, then print the value of count as the result.
    • If the current element in the array tmp[] is at least 0 and the value of i * tmp[i] is at least K, then perform the following steps:
      • If K is divisible by the current index, then increment the value of count by K / i.
      • Otherwise, increment the value of count by K/i +1.
  • After completing the above steps, print -1 if it is not possible to schedule all processes. Otherwise, print the count as the minimum time required.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find minimum required
// time to schedule all process
int minTime(int A[], int n, int K)
{
     
    // Stores max element from A[]
    int max_ability = A[0];
 
    // Find the maximum element
    for(int i = 1; i < n; i++)
    {
        max_ability = max(max_ability, A[i]);
    }
 
    // Stores frequency of each element
    int tmp[max_ability + 1] = {0};
 
    // Stores minimum time required
    // to schedule all process
    int count = 0;
 
    // Count frequencies of elements
    for(int i = 0; i < n; i++)
    {
        tmp[A[i]]++;
    }
 
    // Find the minimum time
    for(int i = max_ability; i >= 0; i--)
    {
        if (tmp[i] != 0)
        {
            if (tmp[i] * i < K)
            {
                 
                // Decrease the value
                // of K
                K -= (i * tmp[i]);
 
                // Increment tmp[i/2]
                tmp[i / 2] += tmp[i];
 
                // Increment the count
                count += tmp[i];
 
                // Return count, if all
                // process are scheduled
                if (K <= 0)
                {
                    return count;
                }
            }
 
            else
            {
                 
                // Increment count
                if (K % i != 0)
                {
                    count += (K / i) + 1;
                }
                else
                {
                    count += (K / i);
                }
 
                // Return the count
                return count;
            }
        }
    }
 
    // If it is not possible to
    // schedule all process
    return -1;
}
 
// Driver code
int main()
{
    int arr[] = { 3, 1, 7, 2, 4 };
    int N = 5;
    int K = 15;
     
    cout << minTime(arr, N, K);
     
    return 0;
}
 
// This code is contributed by mohit kumar 29


Java




// Java program for the above approach
 
import java.util.*;
import java.lang.*;
 
class GFG {
 
    // Function to find minimum required
    // time to schedule all process
    static int minTime(int[] A, int n, int K)
    {
        // Stores max element from A[]
        int max_ability = A[0];
 
        // Find the maximum element
        for (int i = 1; i < n; i++) {
            max_ability = Math.max(
                max_ability, A[i]);
        }
 
        // Stores frequency of each element
        int tmp[] = new int[max_ability + 1];
 
        // Stores minimum time required
        // to schedule all process
        int count = 0;
 
        // Count frequencies of elements
        for (int i = 0; i < n; i++) {
            tmp[A[i]]++;
        }
 
        // Find the minimum time
        for (int i = max_ability;
             i >= 0; i--) {
 
            if (tmp[i] != 0) {
 
                if (tmp[i] * i < K) {
 
                    // Decrease the value
                    // of K
                    K -= (i * tmp[i]);
 
                    // Increment tmp[i/2]
                    tmp[i / 2] += tmp[i];
 
                    // Increment the count
                    count += tmp[i];
 
                    // Return count, if all
                    // process are scheduled
                    if (K <= 0) {
                        return count;
                    }
                }
 
                else {
 
                    // Increment count
                    if (K % i != 0) {
                        count += (K / i) + 1;
                    }
                    else {
                        count += (K / i);
                    }
 
                    // Return the count
                    return count;
                }
            }
        }
 
        // If it is not possible to
        // schedule all process
        return -1;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 3, 1, 7, 2, 4 };
        int N = arr.length;
        int K = 15;
        System.out.println(
            minTime(arr, N, K));
    }
}


Python3




# Python3 program for the above approach
 
# Function to find minimum required
# time to schedule all process
def minTime(A, n, K):
     
    # Stores max element from A[]
    max_ability = A[0]
 
    # Find the maximum element
    for i in range(1, n):
        max_ability = max(max_ability, A[i])
 
    # Stores frequency of each element
    tmp = [0 for i in range(max_ability + 1)]
 
    # Stores minimum time required
    # to schedule all process
    count = 0
 
    # Count frequencies of elements
    for i in range(n):
        tmp[A[i]] += 1
 
    # Find the minimum time
    i = max_ability
     
    while(i >= 0):
        if (tmp[i] != 0):
            if (tmp[i] * i < K):
                 
                # Decrease the value
                # of K
                K -= (i * tmp[i])
 
                # Increment tmp[i/2]
                tmp[i // 2] += tmp[i]
 
                # Increment the count
                count += tmp[i]
 
                # Return count, if all
                # process are scheduled
                if (K <= 0):
                    return count
            else:
                 
                # Increment count
                if (K % i != 0):
                    count += (K // i) + 1
                else:
                    count += (K // i)
 
                # Return the count
                return count
        i -= 1
 
    # If it is not possible to
    # schedule all process
    return -1
 
# Driver code
if __name__ == '__main__':
     
    arr = [ 3, 1, 7, 2, 4 ]
    N = 5
    K = 15
     
    print(minTime(arr, N, K))
 
# This code is contributed by SURENDRA_GANGWAR


C#




// C# program for the above approach
using System;
 
class GFG{
 
// Function to find minimum required
// time to schedule all process
static int minTime(int[] A, int n, int K)
{
     
    // Stores max element from A[]
    int max_ability = A[0];
 
    // Find the maximum element
    for(int i = 1; i < n; i++)
    {
        max_ability = Math.Max(
            max_ability, A[i]);
    }
 
    // Stores frequency of each element
    int []tmp = new int[max_ability + 1];
 
    // Stores minimum time required
    // to schedule all process
    int count = 0;
 
    // Count frequencies of elements
    for(int i = 0; i < n; i++)
    {
        tmp[A[i]]++;
    }
     
    // Find the minimum time
    for(int i = max_ability; i >= 0; i--)
    {
        if (tmp[i] != 0)
        {
            if (tmp[i] * i < K)
            {
                 
                // Decrease the value
                // of K
                K -= (i * tmp[i]);
 
                // Increment tmp[i/2]
                tmp[i / 2] += tmp[i];
 
                // Increment the count
                count += tmp[i];
 
                // Return count, if all
                // process are scheduled
                if (K <= 0)
                {
                    return count;
                }
            }
 
            else
            {
                 
                // Increment count
                if (K % i != 0)
                {
                    count += (K / i) + 1;
                }
                else
                {
                    count += (K / i);
                }
 
                // Return the count
                return count;
            }
        }
    }
 
    // If it is not possible to
    // schedule all process
    return -1;
}
 
// Driver Code
public static void Main(string[] args)
{
    int []arr = { 3, 1, 7, 2, 4 };
    int N = arr.Length;
    int K = 15;
     
    Console.WriteLine(minTime(arr, N, K));
}
}
 
// This code is contributed by ukasp


Javascript




<script>
 
// JavaScript Program to implement
// the above approach
 
    // Function to find minimum required
    // time to schedule all process
    function minTime(A, n, K)
    {
        // Stores max element from A[]
        let max_ability = A[0];
  
        // Find the maximum element
        for (let i = 1; i < n; i++) {
            max_ability = Math.max(
                max_ability, A[i]);
        }
  
        // Stores frequency of each element
        let tmp =
        Array.from({length: max_ability + 1}, (_, i) => 0);
  
        // Stores minimum time required
        // to schedule all process
        let count = 0;
  
        // Count frequencies of elements
        for (let i = 0; i < n; i++) {
            tmp[A[i]]++;
        }
  
        // Find the minimum time
        for (let i = max_ability;
             i >= 0; i--) {
  
            if (tmp[i] != 0) {
  
                if (tmp[i] * i < K) {
  
                    // Decrease the value
                    // of K
                    K -= (i * tmp[i]);
  
                    // Increment tmp[i/2]
                    tmp[(i / 2)] += tmp[i];
  
                    // Increment the count
                    count += tmp[i];
  
                    // Return count, if all
                    // process are scheduled
                    if (K <= 0) {
                        return count;
                    }
                }
  
                else {
  
                    // Increment count
                    if (K % i != 0) {
                        count += Math.floor(K / i) + 1;
                    }
                    else {
                        count += Math.floor(K / i);
                    }
  
                    // Return the count
                    return count;
                }
            }
        }
  
        // If it is not possible to
        // schedule all process
        return -1;
    }
 
// Driver Code
 
     let arr = [ 3, 1, 7, 2, 4 ];
     let N = arr.length;
     let K = 15;
     document.write( minTime(arr, N, K));
 
</script>


Output

4

Time Complexity: O(M), where M is the maximum element in the array.
Auxiliary Space: O(M)

Alternative Approach(Using STL): The given problem can be solved by using the Greedy Approach with the help of max-heap. Follow the steps below to solve the problem:

  • Initialize a priority queue, say PQ, and insert all the elements of the given array into PQ.
  • Initialize a variable, say ans as 0 to store the resultant maximum diamond gained.
  • Iterate a loop until the priority queue PQ is not empty and the value of K > 0:
    • Pop the top element of the priority queue and add the popped element to the variable ans.
    • Divide the popped element by 2 and insert it into the priority queue PQ.
    • Decrement the value of K by 1.
  • After completing the above steps, print the value of ans as the result.

Below is the implementation of the above approach:

C++14




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to execute k processes that can be gained in
// minimum amount of time
void executeProcesses(int A[], int N, int K)
{
    // Stores all the array elements
    priority_queue<int> pq;
 
    // Push all the elements to the
    // priority queue
    for (int i = 0; i < N; i++) {
        pq.push(A[i]);
    }
 
    // Stores the required result
    int ans = 0;
 
    // Loop while the queue is not
    // empty and K is positive
    while (!pq.empty() && K > 0) {
 
        // Store the top element
        // from the pq
        int top = pq.top();
 
        // Pop it from the pq
        pq.pop();
 
        // Add it to the answer
        ans ++;
 
        // Divide it by 2 and push it
        // back to the pq
        K = K - top;
        top = top / 2;
        pq.push(top);
    }
 
    // Print the answer
    cout << ans;
}
 
// Driver Code
int main()
{
    int A[] = { 3, 1, 7, 4, 2 };
    int K = 15;
    int N = sizeof(A) / sizeof(A[0]);
    executeProcesses(A, N, K);
 
    return 0;
}


Python3




# Python3 program for the above approach
  
# Function to execute k processes that
# can be gained in minimum amount of time
def executeProcesses(A, N, K):
     
    # Stores all the array elements
    pq = []
     
    # Push all the elements to the
    # priority queue
    for i in range(N):
        pq.append(A[i])
     
    # Stores the required result
    ans = 0
    pq.sort()
     
    # Loop while the queue is not
    # empty and K is positive
    while (len(pq) > 0 and K > 0):
         
        # Store the top element
        # from the pq
        top = pq.pop()
         
        # Add it to the answer
        ans += 1
         
        # Divide it by 2 and push it
        # back to the pq
        K -= top
        top //=2
        pq.append(top)
         
        pq.sort()
     
    # Print the answer
    print(ans)
 
# Driver Code
A = [ 3, 1, 7, 4, 2 ]
K = 15
N=len(A)
executeProcesses(A, N, K)
 
#  This code is contributed by patel2127


Javascript




<script>
 
// Javascript program for the above approach
 
// Function to execute k processes that
// can be gained in minimum amount of time
function executeProcesses(A, N, K)
{
     
    // Stores all the array elements
    let pq = [];
     
    // Push all the elements to the
    // priority queue
    for(let i = 0; i < N; i++)
    {
        pq.push(A[i]);
    }
  
    // Stores the required result
    let ans = 0;
     pq.sort(function(a, b){return a - b;});
      
    // Loop while the queue is not
    // empty and K is positive
    while (pq.length > 0 && K > 0)
    {
         
        // Store the top element
        // from the pq
        let top = pq.pop();
      
        // Add it to the answer
        ans++;
  
        // Divide it by 2 and push it
        // back to the pq
        K -= top;
        top = Math.floor(top / 2);
        pq.push(top);
         
        pq.sort(function(a, b){return a - b;});
    }
     
    // Print the answer
    document.write(ans)
}
 
// Driver Code
let A = [ 3, 1, 7, 4, 2 ];
let K = 15;
let N = A.length;
 
executeProcesses(A, N, K);
 
// This code is contributed by avanitrachhadiya2155
 
</script>


Java




/*package whatever //do not write package name here */
 
import java.util.*;
 
class GFG {
   
   
// Function to execute k processes that can be gained in
// minimum amount of time
static void executeProcesses(int A[], int N, int K)
{
    // Stores all the array elements
    PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());
 
    // Push all the elements to the
    // priority queue
    for (int i = 0; i < N; i++) {
        pq.add(A[i]);
    }
 
    // Stores the required result
    int ans = 0;
 
    // Loop while the queue is not
    // empty and K is positive
    while (!pq.isEmpty() && K > 0) {
 
        // Store the top element
        // from the pq
        int top = pq.poll();
 
 
        // Add it to the answer
        ans++;
 
        // Divide it by 2 and push it
        // back to the pq
        K = K - top;
        top = top>>1;
        pq.add(top);
    }
 
    // Print the answer
    System.out.println(ans);
}
   
    public static void main (String[] args) {
         
      int A[] = { 3, 1, 7, 4, 2 };
    int K = 15;
    int N = A.length;
    executeProcesses(A, N, K);
 
    }
}


C#




using System;
using System.Linq;
using System.Collections.Generic;
 
class Program
{
    class PriorityQueue
    {
        private List<int> heap;
        private int size;
        private IComparer<int> comparer;
 
        public PriorityQueue()
        {
            heap = new List<int>();
            size = 0;
            comparer = Comparer<int>.Default;
        }
 
        public int Count
        {
            get { return size; }
        }
 
        public void Enqueue(int item)
        {
            heap.Add(item);
            size++;
            HeapifyUp(size - 1);
        }
 
        public int Dequeue()
        {
            if (size == 0)
            {
                throw new InvalidOperationException("Queue is empty");
            }
 
            int item = heap[0];
            heap[0] = heap[size - 1];
            heap.RemoveAt(size - 1);
            size--;
            HeapifyDown(0);
            return item;
        }
 
        private void HeapifyUp(int index)
        {
            int parent = (index - 1) / 2;
            if (index > 0 && comparer.Compare(heap[index], heap[parent]) > 0)
            {
                Swap(index, parent);
                HeapifyUp(parent);
            }
        }
 
        private void HeapifyDown(int index)
        {
            int left = 2 * index + 1;
            int right = 2 * index + 2;
            int largest = index;
            if (left < size && comparer.Compare(heap[left], heap[largest]) > 0)
            {
                largest = left;
            }
            if (right < size && comparer.Compare(heap[right], heap[largest]) > 0)
            {
                largest = right;
            }
            if (largest != index)
            {
                Swap(index, largest);
                HeapifyDown(largest);
            }
        }
 
        private void Swap(int index1, int index2)
        {
            int temp = heap[index1];
            heap[index1] = heap[index2];
            heap[index2] = temp;
        }
    }
 
    // Function to execute k processes that can be gained in
    // minimum amount of time
    static void ExecuteProcesses(int[] A, int N, int K)
    {
        // Stores all the array elements
        PriorityQueue pq = new PriorityQueue();
 
      for (int i = 0; i < N; i++) {
        pq.Enqueue(A[i]);
    }
 
       
        // Stores the required result
        int ans = 0;
 
        // Loop while the queue is not
        // empty and K is positive
        while (pq.Count > 0 && K > 0)
        {
            // Store the top element
            // from the pq
            int top = pq.Dequeue();
 
            // Add it to the answer
            ans++;
 
            // Divide it by 2 and push it
            // back to the pq
            K = K - top;
            top = top >> 1;
            pq.Enqueue(top);
        }
 
        // Print the answer
        Console.WriteLine(ans);
    }
 
    public static void Main(string[] args)
    {
        int[] A = { 3, 1, 7, 4, 2 };
        int K = 15;
        int N = A.Length;
        ExecuteProcesses(A, N, K);
    }
}


Output

4

Time Complexity: O((N + K)*log N)

Auxiliary Space: O(N)


My Personal Notes arrow_drop_up
Last Updated : 04 Feb, 2023
Like Article
Save Article
Similar Reads
Related Tutorials