2024-5-4
题目来源
我的题解
方法一 动态规划+二分查找
参考官方题解。
关键在于动态转移方程的构建:
兼职工作由开始时间 startTime,结束时间 endTime和预计报酬 profit 三种属性表示。首先将兼职工作按结束时间 endTime 从小到大进行排序。使用 dp[i] 表示前 i 份兼职工作可以获得的最大报酬,即区间 [0,i−1] 的所有兼职工作可以获得的最大报酬。初始时 dp[0]=0,表示没有兼职工作时报酬为 0。那么对于 i>0,根据第 i−1 份兼职工作是否被选择,有以下转移方程:
dp [ i ] = max ( dp [ i − 1 ] , dp [ k ] + profit [ i − 1 ] ) \textit{dp}[i] = \max(\textit{dp}[i - 1], \textit{dp}[k] + \textit{profit}[i - 1]) dp[i]=max(dp[i−1],dp[k]+profit[i−1])。其中 k 表示满足结束时间小于等于第 i−1份工作开始时间的兼职工作数量(因为兼职工作是按照结束时间从小到大进行排序的,所以选择第 i−1 份兼职工作后,只能继续选择前 k 份兼职工作),可以通过二分查找获得。
时间复杂度:O(nlogn),其中 n 是兼职工作的数量。排序需要 O(nlogn),遍历 + 二分查找需要 O(nlogn),因此总时间复杂度为 O(nlogn)。
空间复杂度:O(n)。需要 O(n) 的空间来保存 dp。
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
int n=startTime.length;
int[][] jobs=new int[n][3];
for(int i=0;i<n;i++){
jobs[i][0]=startTime[i];
jobs[i][1]=endTime[i];
jobs[i][2]=profit[i];
}
Arrays.sort(jobs,(a,b)->a[1]-b[1]);
int[] dp=new int[n+1];
for(int i=1;i<=n;i++){
int k=binarySearch(jobs,i-1,jobs[i-1][0]);
dp[i]=Math.max(dp[i-1],dp[k]+jobs[i-1][2]);
}
return dp[n];
}
public int binarySearch(int[][] jobs,int end,int startTime){
int left=0,right=end;
while(left<right){
int mid=((right-left)>>1)+left;
//结束时间比开始时间晚
if(jobs[mid][1]>startTime){
right=mid;
//结束时间小于等开始时间
}else{
left=mid+1;
}
}
return left;
}
方法二
时间复杂度:
空间复杂度:
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~