Find minimum time to finish all jobs with given constraints
Given an array job[], where each element represents the time required to complete a specific job. There are k identical assignees available to complete these jobs, and each assignee takes t units of time to complete one unit of a job. The task is to determine the minimum time required to complete all jobs while following these constraints:
- Each assignee can only be assigned jobs that are contiguous in the given array. For example, an assignee can be assigned jobs (job[1], job[2], job[3]) but not (job[1], job[3]) (skipping job[2]).
- A single job cannot be divided between two assignees. Each job must be assigned to exactly one assignee.
Examples:
Input: job[] = {10, 7, 8, 12, 6, 8}, k = 4, t = 5
Output: 75
Explanation: The minimum time required to finish all the jobs is 75.
- Assign {10} to the first assignee.
- Assign {7, 8} to the second assignee.
- Assign {12} to the third assignee.
- Assign {6, 8} to the fourth assignee.
- Maximum time taken by any assignee is (12 * 5) = 75.
Input: job[] = {4, 5, 10}, k = 2, t = 5
Output: 50
Explanation: The minimum time required to finish all the jobs is 50.
- Assign {4, 5} to the first assignee.
- Assign {10} to the second assignee.
- Maximum time taken by any assignee is (4 + 5) * 5 = 50.
This problem is mainly a variation of Allocate Minimum Pages
The idea is to use Binary Search, as we observe that the total job sum gives an upper bound, and the maximum job gives a lower bound. Using binary search between these bounds helps efficiently find the minimum feasible time. The key observation is that for a given time t, we can check if the jobs can be assigned within k assignees using a greedy approach. If it is possible, we try to minimize t further; otherwise, we increase it. This ensures an optimal partitioning of jobs while keeping time minimal.
Steps to implement the above idea:
- Calculate the maximum job duration and total job sum to determine the search range.
- Use binary search between the maximum job time and the total job time to find the minimum feasible time.
- Implement a function to assign jobs to assignees while ensuring no one exceeds the given time limit.
- If jobs can be completed within the current mid-value, update the answer and reduce the search space; otherwise, increase the lower bound.
- Multiply the minimum feasible time by the given multiplier and print the result.
Below is the implementation of the above approach:
// C++ program to find the minimum time required
// to finish all jobs using Binary Search
#include <bits/stdc++.h>
using namespace std;
// Function to find the maximum job duration
int getMax(vector<int> &job) {
int res = job[0];
// Find the maximum time among all jobs
for (int i = 1; i < job.size(); i++) {
if (job[i] > res) {
res = job[i];
}
}
return res;
}
// Function to check if jobs can be completed within
// 't' time using at most 'k' assignees
bool isPossible(vector<int> &job, int t, int k) {
// Number of assignees required
int cnt = 1;
// Time assigned to the current assignee
int curr = 0;
for (int i = 0; i < job.size();) {
// If adding the current job exceeds 't',
// assign a new assignee
if (curr + job[i] > t) {
curr = 0;
cnt++;
} else {
// Otherwise, add job time to the
// current assignee
curr += job[i];
i++;
}
}
return (cnt <= k);
}
// Function to find the minimum time required to
// finish all jobs
int findMinTime(vector<int> &job, int k, int t) {
int start = 0, end = 0, ans;
// Compute the total time and the maximum
// job duration
for (int j : job) {
// Total sum of job times
end += j;
// Maximum job duration
start = max(start, j);
}
// Initialize answer to the upper bound
ans = end;
// Perform binary search to find the minimum
// feasible time
while (start <= end) {
int mid = (start + end) / 2;
// If jobs can be assigned within 'mid' time
if (isPossible(job, mid, k)) {
ans = min(ans, mid);
end = mid - 1;
} else {
start = mid + 1;
}
}
// Return the minimum time required
return ans * t;
}
int main() {
vector<int> job = {10, 7, 8, 12, 6, 8};
int k = 4, t = 5;
cout << findMinTime(job, k, t) << endl;
return 0;
}
// Java program to find the minimum time required
// to finish all jobs using Binary Search
import java.util.*;
class GfG {
// Function to find the maximum job duration
static int getMax(int job[]) {
int res = job[0];
// Find the maximum time among all jobs
for (int i = 1; i < job.length; i++) {
if (job[i] > res) {
res = job[i];
}
}
return res;
}
// Function to check if jobs can be completed within
// 't' time using at most 'k' assignees
static boolean isPossible(int job[], int t, int k) {
// Number of assignees required
int cnt = 1;
// Time assigned to the current assignee
int curr = 0;
for (int i = 0; i < job.length;) {
// If adding the current job exceeds 't',
// assign a new assignee
if (curr + job[i] > t) {
curr = 0;
cnt++;
} else {
// Otherwise, add job time to the
// current assignee
curr += job[i];
i++;
}
}
return (cnt <= k);
}
// Function to find the minimum time required to
// finish all jobs
static int findMinTime(int job[], int k, int t) {
int start = 0, end = 0, ans;
// Compute the total time and the maximum
// job duration
for (int j : job) {
// Total sum of job times
end += j;
// Maximum job duration
start = Math.max(start, j);
}
// Initialize answer to the upper bound
ans = end;
// Perform binary search to find the minimum
// feasible time
while (start <= end) {
int mid = (start + end) / 2;
// If jobs can be assigned within 'mid' time
if (isPossible(job, mid, k)) {
ans = Math.min(ans, mid);
end = mid - 1;
} else {
start = mid + 1;
}
}
// Return the minimum time required
return ans * t;
}
public static void main(String[] args) {
int job[] = {10, 7, 8, 12, 6, 8};
int k = 4, t = 5;
System.out.println(findMinTime(job, k, t));
}
}
# Python program to find the minimum time required
# to finish all jobs using Binary Search
# Function to find the maximum job duration
def GetMax(job):
res = job[0]
# Find the maximum time among all jobs
for i in range(1, len(job)):
if job[i] > res:
res = job[i]
return res
# Function to check if jobs can be completed within
# 't' time using at most 'k' assignees
def IsPossible(job, t, k):
# Number of assignees required
cnt = 1
# Time assigned to the current assignee
curr = 0
i = 0
while i < len(job):
# If adding the current job exceeds 't',
# assign a new assignee
if curr + job[i] > t:
curr = 0
cnt += 1
else:
# Otherwise, add job time to the
# current assignee
curr += job[i]
i += 1
return cnt <= k
# Function to find the minimum time required to
# finish all jobs
def FindMinTime(job, k, t):
start, end = 0, 0
# Compute the total time and the maximum
# job duration
for j in job:
# Total sum of job times
end += j
# Maximum job duration
start = max(start, j)
# Initialize answer to the upper bound
ans = end
# Perform binary search to find the minimum
# feasible time
while start <= end:
mid = (start + end) // 2
# If jobs can be assigned within 'mid' time
if IsPossible(job, mid, k):
ans = min(ans, mid)
end = mid - 1
else:
start = mid + 1
# Return the minimum time required
return ans * t
if __name__ == "__main__":
job = [10, 7, 8, 12, 6, 8]
k, t = 4, 5
print(FindMinTime(job, k, t))
// C# program to find the minimum time required
// to finish all jobs using Binary Search
using System;
class GfG {
// Function to find the maximum job duration
static int GetMax(int[] job) {
int res = job[0];
// Find the maximum time among all jobs
for (int i = 1; i < job.Length; i++) {
if (job[i] > res) {
res = job[i];
}
}
return res;
}
// Function to check if jobs can be completed within
// 't' time using at most 'k' assignees
static bool IsPossible(int[] job, int t, int k) {
// Number of assignees required
int cnt = 1;
// Time assigned to the current assignee
int curr = 0;
for (int i = 0; i < job.Length;) {
// If adding the current job exceeds 't',
// assign a new assignee
if (curr + job[i] > t) {
curr = 0;
cnt++;
} else {
// Otherwise, add job time to the
// current assignee
curr += job[i];
i++;
}
}
return (cnt <= k);
}
// Function to find the minimum time required to
// finish all jobs
static int FindMinTime(int[] job, int k, int t) {
int start = 0, end = 0, ans;
// Compute the total time and the maximum
// job duration
foreach (int j in job) {
// Total sum of job times
end += j;
// Maximum job duration
start = Math.Max(start, j);
}
// Initialize answer to the upper bound
ans = end;
// Perform binary search to find the minimum
// feasible time
while (start <= end) {
int mid = (start + end) / 2;
// If jobs can be assigned within 'mid' time
if (IsPossible(job, mid, k)) {
ans = Math.Min(ans, mid);
end = mid - 1;
} else {
start = mid + 1;
}
}
// Return the minimum time required
return ans * t;
}
public static void Main() {
int[] job = {10, 7, 8, 12, 6, 8};
int k = 4, t = 5;
Console.WriteLine(FindMinTime(job, k, t));
}
}
// JavaScript program to find the minimum time required
// to finish all jobs using Binary Search
// Function to find the maximum job duration
function GetMax(job) {
let res = job[0];
// Find the maximum time among all jobs
for (let i = 1; i < job.length; i++) {
if (job[i] > res) {
res = job[i];
}
}
return res;
}
// Function to check if jobs can be completed within
// 't' time using at most 'k' assignees
function IsPossible(job, t, k) {
// Number of assignees required
let cnt = 1;
// Time assigned to the current assignee
let curr = 0;
let i = 0;
while (i < job.length) {
// If adding the current job exceeds 't',
// assign a new assignee
if (curr + job[i] > t) {
curr = 0;
cnt++;
} else {
// Otherwise, add job time to the
// current assignee
curr += job[i];
i++;
}
}
return cnt <= k;
}
// Function to find the minimum time required to
// finish all jobs
function FindMinTime(job, k, t) {
let start = 0, end = 0;
// Compute the total time and the maximum
// job duration
for (let j of job) {
// Total sum of job times
end += j;
// Maximum job duration
start = Math.max(start, j);
}
// Initialize answer to the upper bound
let ans = end;
// Perform binary search to find the minimum
// feasible time
while (start <= end) {
let mid = Math.floor((start + end) / 2);
// If jobs can be assigned within 'mid' time
if (IsPossible(job, mid, k)) {
ans = Math.min(ans, mid);
end = mid - 1;
} else {
start = mid + 1;
}
}
// Return the minimum time required
return ans * t;
}
// Driver Code
let job = [10, 7, 8, 12, 6, 8];
let k = 4, t = 5;
console.log(FindMinTime(job, k, t));
Output:
75
Time Complexity: O(n log(sum(job))) due to binary search over the time range and checking feasibility in O(n).
Space Complexity: O(1) as only a few integer variables are used, and no extra data structures are allocated.