You want to schedule a list of jobs in d
days. Jobs are dependent (i.e To work on the i
th job, you have to finish all the jobs j
where 0 <= j < i
).
You have to finish at least one task every day. The difficulty of a job schedule is the sum of difficulties of each day of the d
days. The difficulty of a day is the maximum difficulty of a job done on that day.
You are given an integer array jobDifficulty
and an integer d
. The difficulty of the i
th job is jobDifficulty[i]
.
Return the minimum difficulty of a job schedule. If you cannot find a schedule for the jobs return -1
.
Example 1:
jobDifficulty = [6,5,4,3,2,1], d = 2
Output: 7
Explanation: First day you can finish the first 5 jobs, total difficulty = 6. Second day you can finish the last job, total difficulty = 1. The difficulty of the schedule = 6 + 1 = 7
Example 2:
jobDifficulty = [9,9,9], d = 4
Output: -1
`Explanation: If you finish a job per day you will still have a free day. you cannot find a schedule for the given jobs.
Example 3:
jobDifficulty = [1,1,1], d = 3
Output: 3
`Explanation: The schedule is one job per day. total difficulty will be 3.
Given the above problem, provide an algorithm to solve the problem efficiently, what is the Big(O) run time, and what is the Big(O) space usage?
You are given an array jobDifficulty
representing the difficulty of each job and an integer d
representing the number of days to schedule these jobs. You must schedule at least one job per day, and all jobs must be completed. The difficulty of a day is the maximum difficulty of the jobs done on that day. The goal is to minimize the total difficulty of the schedule, which is the sum of the difficulties of each day. If it's not possible to schedule the jobs in d
days, return -1.
A brute-force approach would involve trying all possible combinations of splitting the jobs into d
days and calculating the total difficulty for each combination. This can be implemented using recursion.
d == 1
, the difficulty is the maximum difficulty among the remaining jobs.def minDifficulty_brute_force(jobDifficulty, d):
n = len(jobDifficulty)
if n < d:
return -1
def solve(index, days_left):
if days_left == 1:
return max(jobDifficulty[index:])
min_diff = float('inf')
curr_max = 0
for i in range(index, n - days_left + 1):
curr_max = max(curr_max, jobDifficulty[i])
min_diff = min(min_diff, curr_max + solve(i + 1, days_left - 1))
return min_diff
return solve(0, d)
The brute-force approach has exponential time complexity since it explores all possible combinations of job schedules. The complexity is roughly O(N^D), where N is the number of jobs and D is the number of days.
The space complexity is O(D) due to the recursion depth.
To optimize the solution, we can use dynamic programming to avoid redundant calculations. We create a DP table dp[i][j]
, where dp[i][j]
represents the minimum difficulty to schedule the first i
jobs in j
days.
dp[i][1]
is the maximum difficulty of the first i
jobs.dp[i][j] = min(dp[k][j-1] + max_difficulty(k+1, i))
for all k
from j-1
to i-1
, where max_difficulty(k+1, i)
is the maximum difficulty among jobs from k+1
to i
.def minDifficulty(jobDifficulty, d):
n = len(jobDifficulty)
if n < d:
return -1
dp = [[float('inf')] * (d + 1) for _ in range(n + 1)]
dp[0][0] = 0
for j in range(1, d + 1):
for i in range(j, n + 1):
max_d = 0
for k in range(i - 1, j - 2, -1):
max_d = max(max_d, jobDifficulty[k])
dp[i][j] = min(dp[i][j], dp[k][j - 1] + max_d)
return dp[n][d]
The dynamic programming approach has a time complexity of O(N^2 * D), where N is the number of jobs and D is the number of days. This is because we have three nested loops: one for days, one for jobs, and one for the split point k
.
The space complexity is O(N * D) due to the size of the DP table.
d == 1
, the minimum difficulty is the maximum of all job difficulties.For jobDifficulty = [6, 5, 4, 3, 2, 1]
and d = 2
, the optimal solution using dynamic programming would be as follows:
The dp
table would be built up, and dp[6][2]
would contain the minimum difficulty, which is 7.
The optimal approach using dynamic programming provides an efficient way to solve this problem with a time complexity of O(N^2 * D) and a space complexity of O(N * D). This avoids the exponential time complexity of the brute-force approach. Handling edge cases ensures the solution is robust for all valid inputs.