(LeetCode 每日一题) 3440. 重新安排会议得到最多空余时间 II (贪心)
题目:3440. 重新安排会议得到最多空余时间 II
思路:(LeetCode 每日一题 ) 3439. 重新安排会议得到最多空余时间 I (滑动窗口)的进阶版。
在得到空闲数组v之后,本质就是枚举移动每一个活动,观察是否有除了其左右两边空闲位置外,还有没有不小于这个活动长度的空闲位置。细节看注释
C++版本:
class Solution {
public:int maxFreeTime(int eventTime, vector<int>& startTime, vector<int>& endTime) {// 空闲位置数组,空闲为0也要记录vector<int> v;int last=0;for(int i=0;i<startTime.size();i++){v.push_back(startTime[i]-last);last=endTime[i];}if(last<=eventTime){v.push_back(eventTime-last);}// q[i]表示:在i的右边最大的空闲位置int n=v.size();vector<int> q(n);q[n-1]=0;for(int i=n-2;i>=0;i--){q[i]=max(q[i+1],v[i+1]);}//已遍历过的空闲位置的最大值int mx=0;// 答案int ans=0;// 遍历,来枚举每一个活动被移动for(int i=1;i<n;i++){// 第一个活动和0之间有一个空闲位置,所以活动的下标是i-1// 第i-1活动左右两边空闲位置int t=v[i-1]+v[i];// 第i-1活动的长度int len=endTime[i-1]-startTime[i-1];// 有不小于这个活动长度的空闲位置if(len<=mx || len<=q[i]){// 可加上当前活动的长度lenans=max(ans,len+t);}else{// 只能将当前活动移动到左右两侧ans=max(ans,t);}// 维护已遍历过的空闲位置的最大值mx=max(mx,v[i-1]);}return ans;}
};
JAVA版本:
class Solution {public int maxFreeTime(int eventTime, int[] startTime, int[] endTime) {List<Integer> v=new ArrayList<>();int last=0;for(int i=0;i<startTime.length;i++){v.add(startTime[i]-last);last=endTime[i];}if(last<=eventTime){v.add(eventTime-last);}int n=v.size();int[] q=new int[n];q[n-1]=0;for(int i=n-2;i>=0;i--){q[i]=Math.max(q[i+1],v.get(i+1));}int mx=0;int ans=0;for(int i=1;i<n;i++){int t=v.get(i-1)+v.get(i);int len=endTime[i-1]-startTime[i-1];if(len<=mx || len<=q[i]){ans=Math.max(ans,len+t);}else{ans=Math.max(ans,t);}mx=Math.max(mx,v.get(i-1));}return ans;}
}
GO版本:
func maxFreeTime(eventTime int, startTime []int, endTime []int) int {v:=[]int{}n:=len(startTime)last:=0for i:=0;i<n;i++ {v=append(v,startTime[i]-last)last=endTime[i]}if last<=eventTime {v=append(v,eventTime-last)}n=len(v)q:=make([]int,n)q[n-1]=0for i:=n-2;i>=0;i-- {q[i]=max(q[i+1],v[i+1])}mx:=0ans:=0for i:=1;i<n;i++ {len:=endTime[i-1]-startTime[i-1]t:=v[i]+v[i-1]if len<=mx || len<=q[i] {ans=max(ans,t+len)}else{ans=max(ans,t)}mx=max(mx,v[i-1])}return ans
}