日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Leetcode 1235. Maximum Profit in Job Scheduling (python)

發布時間:2024/3/7 python 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Leetcode 1235. Maximum Profit in Job Scheduling (python) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Leetcode 1235. Maximum Profit in Job Scheduling

  • 題目
  • 解法1:dp
  • 解法2:dp+binary search
  • 二刷

題目

解法1:dp

這倒題目用dp來做是挺明顯的,但是dp的元素代表什么很關鍵。如果dp元素代表時間的話,那這個題目就很難做了。正確的做法應該是用區間來代表dp的元素,這樣就變成了對于每個元素取或者不取兩種情況了。具體的解法如下:

  • 將各個區間按照結尾進行排序
  • dp[i]代表從前i個區間中選擇,最多可以獲取多大的利潤
  • 對于第i個區間,分取和不取兩種情況
  • 如果取第i個區間,那么需要向前找到j區間,這個區間的結束時間在i區間開始時間之前,這樣總理論就等于從前j個區間中取獲得的利潤加上第i個區間的利潤
    狀態轉移方程
dp[i] = max(dp[i-1],dp[j]+profit_i) where j is the first nonoverlapping interval to i class Solution:def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:n = len(startTime)segments = []for i in range(n):segments.append([startTime[i],endTime[i],profit[i]])segments.sort(key=lambda x:x[1])dp = [0]*nfor i in range(n):# if we don't take iif i>0:dp[i] = dp[i-1]# if we take ifor j in range(i-1,-1,-1):if segments[j][1]<=segments[i][0]:dp[i] = max(dp[i],dp[j]+segments[i][2])break# take into count when interval i is the first onedp[i] = max(dp[i],segments[i][2])return dp[-1]

對于最后一行是必須要的,第一個原因是dp[0]需要初始化。另外更重要的原因舉個例子,如果第一個區間是[2,3], profit是10,第二個區間是[1,4],profit是100.這個時候dp[0]=10,但是如果沒有最后一個比較,dp[1]會是10,而正確的應該是100

解法2:dp+binary search

利用左閉右開尋找第一個符合條件的區間j。關于二分的學習,看這里https://blog.csdn.net/qq_37821701/article/details/108772806

class Solution:def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:n = len(startTime)segments = []for i in range(n):segments.append([startTime[i],endTime[i],profit[i]])segments.sort(key=lambda x:x[1])dp = [0]*nfor i in range(n):# if we don't take iif i>0:dp[i] = dp[i-1]# if we take il = 0r = iwhile l+1<r:mid = l+(r-l)//2if segments[mid][1]<=segments[i][0]:l = midelse:r = midif segments[l][1]<=segments[i][0]:dp[i] = max(dp[i],dp[l]+segments[i][2])dp[i] = max(dp[i],segments[i][2])return dp[-1]

上面兩種解法,對于大數據規模來說肯定是解法2更快,但實際上這兩道題leetcode的測試數據很小,所以解法一提交結果更快

二刷

一開始的時候還是寫了O(n^2)的解法

class Solution { public:static bool comparer(const vector<int>& a, const vector<int>& b){return a[0] < b[0];}int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {vector<vector<int>> jobs;int n = startTime.size();for(int i=0;i<n;i++){jobs.push_back({startTime[i],endTime[i],profit[i]});}sort(jobs.begin(),jobs.end(),comparer);vector<int> dp(n+1,0);// dp[0] = jobs[0][2];for(int i=1;i<n+1;i++){for(int j=i-1;j>=0;j--){if(j == 0 || jobs[j-1][1] <= jobs[i-1][0]){dp[i] = max(dp[i],dp[j]+jobs[i-1][2]);}}}return *max_element(dp.begin(),dp.end());} };

tle了之后想到了用二分搜索,但是實際上上面的dp寫法是不能夠進行二分搜索的。因為上面dp[i]的定義是以i位置的區間作為最后一個job,而且必須是take這個job的。所以當dp過程中往前找的時候,必須要看完全部前面的case才可以,而不是碰到第一個滿足條件的job就可以,這也是為什么做不了二分搜索。
其實做一點改變就可以了,把dp[i]的定義改成到第i個區間截止時間為止,所能得到的最大profit,而不是必須以i個區間為結尾。所以其實本質上是個背包問題。也只需要在代碼里面加上dp[i] = dp[i-1]即可,同時按照結束時間來排序,這樣因為當后面的區間結束的更晚,所以dp[i]必定是大于等于dp[i-1]的,同時注意邊界條件的處理

不用二分搜索的版本:

class Solution { public:static bool comparer(const vector<int>& a, const vector<int>& b){return a[1] < b[1];}int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {vector<vector<int>> jobs;int n = startTime.size();for(int i=0;i<n;i++){jobs.push_back({startTime[i],endTime[i],profit[i]});}sort(jobs.begin(),jobs.end(),comparer);vector<int> dp(n,0);for(int i=0;i<n;i++){if(i > 0){dp[i] = dp[i-1];}dp[i] = max(dp[i],jobs[i][2]);for(int j=i-1;j>=0;j--){if(jobs[j][1] <= jobs[i][0]){dp[i] = max(dp[i],dp[j]+jobs[i][2]);break;}}}return dp.back();} };

加上二分搜索的版本:

class Solution { public:static bool comparer(const vector<int>& a, const vector<int>& b){return a[1] < b[1];}int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {vector<vector<int>> jobs;int n = startTime.size();for(int i=0;i<n;i++){jobs.push_back({startTime[i],endTime[i],profit[i]});}sort(jobs.begin(),jobs.end(),comparer);vector<int> dp(n,0);for(int i=0;i<n;i++){if(i > 0){dp[i] = dp[i-1];}dp[i] = max(dp[i],jobs[i][2]);/*for(int j=i-1;j>=0;j--){if(jobs[j][1] <= jobs[i][0]){dp[i] = max(dp[i],dp[j]+jobs[i][2]);break;}}*/int l = 0;int r = i;while(l+1<r){int mid = l + (r-l)/2;if(jobs[mid][1] > jobs[i][0]){r = mid;}else{l = mid;}}if(jobs[l][1] <= jobs[i][0]){dp[i] = max(dp[i],dp[l]+jobs[i][2]);}}return dp.back();} };

總結

以上是生活随笔為你收集整理的Leetcode 1235. Maximum Profit in Job Scheduling (python)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。