Minimum time required to schedule K processes
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:
- 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.
- The 5th process is scheduled next. The array arr[] modifies to {3, 1, 3, 2, 2}.
- The 1st process is scheduled next. The array arr[] modifies to {1, 1, 3, 2, 2}.
- 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.
- If the current element in tmp[] is greater than 0 and i * tmp[i] is smaller than K.
- 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> |
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); } } |
4
Time Complexity: O((N + K)*log N)
Auxiliary Space: O(N)
Please Login to comment...