There are n
tasks assigned to you. The task times are represented as an integer array tasks
of length n
, where the ith
task takes tasks[i]
hours to finish. A work session is when you work for at most sessionTime
consecutive hours and then take a break.
You should finish the given tasks in a way that satisfies the following conditions:
- If you start a task in a work session, you must complete it in the same work session.
- You can start a new task immediately after finishing the previous one.
- You may complete the tasks in any order.
Given tasks
and sessionTime
, return the minimum number of work sessions needed to finish all the tasks following the conditions above.
The tests are generated such that sessionTime
is greater than or equal to the maximum element in tasks[i]
.
Example 1:
Input: tasks = [1,2,3], sessionTime = 3 Output: 2 Explanation: You can finish the tasks in two work sessions. - First work session: finish the first and the second tasks in 1 + 2 = 3 hours. - Second work session: finish the third task in 3 hours.
Example 2:
Input: tasks = [3,1,3,1,1], sessionTime = 8 Output: 2 Explanation: You can finish the tasks in two work sessions. - First work session: finish all the tasks except the last one in 3 + 1 + 3 + 1 = 8 hours. - Second work session: finish the last task in 1 hour.
Example 3:
Input: tasks = [1,2,3,4,5], sessionTime = 15 Output: 1 Explanation: You can finish all the tasks in one work session.
Constraints:
n == tasks.length
1 <= n <= 14
1 <= tasks[i] <= 10
max(tasks[i]) <= sessionTime <= 15
Similar Questions:
Note that, without precomputing the valid
array, the algorithm takes O(3^N * N)
time, and since N
is at most 14
, it's 66,961,566 ~= 7e7
which is around TLE.
If we precompute the valid
array, 3^14 = 4,782,969 ~= 5e6
which is safe to get passed.
// OJ: https://leetcode.com/problems/minimum-number-of-work-sessions-to-finish-the-tasks/
// Author: github.com/lzl124631x
// Time: O(3^N)
// Space: O(2^N)
class Solution {
int m[16385] = {};
bool valid[16385] = {};
int dp(vector<int> &A, int mask, int total) {
if (mask == 0) return 0;
if (m[mask] != -1) return m[mask];
int ans = INT_MAX;
for (int ms = mask; ms; ms = (ms - 1) & mask) {
if (!valid[ms]) continue;
ans = min(ans, 1 + dp(A, mask & ~ms, total));
}
return m[mask] = ans;
}
public:
int minSessions(vector<int>& A, int total) {
memset(m, -1, sizeof(m));
for (int mask = 1; mask < (1 << A.size()); ++mask) {
int sum = 0;
for (int i = 0; i < A.size(); ++i) {
if (mask >> i & 1) sum += A[i];
}
valid[mask] = sum <= total;
}
return dp(A, (1 << A.size()) - 1, total);
}
};
The time complexity of valid
function has a very loose upper bound O(N^N)
but lots of combinations are skipped so it's way efficient than that.
// OJ: https://leetcode.com/problems/minimum-number-of-work-sessions-to-finish-the-tasks/
// Author: github.com/lzl124631x
// Time: O(logN * N^N)
// Space: O(N)
class Solution {
bool dfs(vector<int> &A, vector<int> &s, int i, int total) {
if (i == A.size()) return true;
for (int j = 0; j < s.size(); ++j) {
if (s[j] + A[i] <= total) {
s[j] += A[i];
if (dfs(A, s, i + 1, total)) return true;
s[j] -= A[i];
}
if (s[j] == 0) break; // Don't try subsequent `0`s since trying them is a waste of time -- trying either `0` session is the same.
}
return false;
}
bool valid(vector<int> &A, int cnt, int total) {
vector<int> s(cnt);
return dfs(A, s, 0, total);
}
public:
int minSessions(vector<int>& A, int total) {
int L = 1, R = A.size();
while (L <= R) {
int M = (L + R) / 2;
if (valid(A, M, total)) R = M - 1;
else L = M + 1;
}
return L;
}
};