【Leetcode】1335. Minimum Difficulty of a Job Schedule
技術標籤:LC 貪心、動態規劃與記憶化搜尋動態規劃leetcode演算法java
題目地址:
https://leetcode.com/problems/minimum-difficulty-of-a-job-schedule/
給定一個長 n n n正整數陣列 A A A和一個正整數 d d d,要求將 A A A分為 d d d個非空子陣列,使得每個子陣列的最大值加起來最小。返回那個最小和。如果不存在切割方案,則返回 − 1 -1 −1。
可以用動態規劃。首先,如果
n
<
d
n<d
n<d,那麼不存在切割方案,則返回
−
1
-1
−1。設
f
[
k
]
[
i
]
f[k][i]
import java.util.Arrays;
public class Solution {
public int minDifficulty(int[] A, int d) {
int n = A.length;
if (n < d) {
return -1;
}
// 初始化為正無窮
int[][] dp = new int[d + 1][n];
for (int[] row : dp) {
Arrays.fill(row, 1 << 30);
}
// 求一下dp[1]
for (int i = n - 1, curMax = 0; i >= 0; i--) {
curMax = Math.max(curMax, A[i]);
dp[1][i] = curMax;
}
for (int i = 2; i <= d; i++) {
for (int j = 0; j <= n - i; j++) {
int curMax = 0;
for (int k = j; k <= n - i; k++) {
curMax = Math.max(curMax, A[k]);
dp[i][j] = Math.min(dp[i][j], curMax + dp[i - 1][k + 1]);
}
}
}
return dp[d][0];
}
}
時間複雜度 O ( d n 2 ) O(dn^2) O(dn2),空間 O ( d n ) O(dn) O(dn)。
可以考慮滾動陣列優化:
import java.util.Arrays;
public class Solution {
public int minDifficulty(int[] A, int d) {
int n = A.length;
if (n < d) {
return -1;
}
int[][] dp = new int[2][n];
for (int i = n - 1, curMax = 0; i >= 0; i--) {
curMax = Math.max(curMax, A[i]);
dp[1][i] = curMax;
}
for (int i = 2; i <= d; i++) {
// 將要計算的那一行初始化為正無窮
Arrays.fill(dp[i & 1], 1 << 30);
for (int j = 0; j <= n - i; j++) {
int curMax = 0;
for (int k = j; k <= n - i; k++) {
curMax = Math.max(curMax, A[k]);
dp[i & 1][j] = Math.min(dp[i & 1][j], curMax + dp[i - 1 & 1][k + 1]);
}
}
}
return dp[d & 1][0];
}
}
時間複雜度不變,空間 O ( n ) O(n) O(n)。