C++二分向量算法:最多可以參加的會議數目 II

本題的其它解法

C++二分算法:最多可以參加的會議數目 II

本文涉及的基礎知識點

二分查找算法合集

題目

給你一個 events 數組,其中 events[i] = [startDayi, endDayi, valuei] ,表示第 i 個會議在 startDayi 天開始,第 endDayi 天結束,如果你參加這個會議,你能得到價值 valuei 。同時給你一個整數 k 表示你能參加的最多會議數目。
你同一時間只能參加一個會議。如果你選擇參加某個會議,那么你必須 完整 地參加完這個會議。會議結束日期是包含在會議內的,也就是說你不能同時參加一個開始日期與另一個結束日期相同的兩個會議。
請你返回能得到的會議價值 最大和 。
示例 1:
輸入:events = [[1,2,4],[3,4,3],[2,3,1]], k = 2
輸出:7
解釋:選擇綠色的活動會議 0 和 1,得到總價值和為 4 + 3 = 7 。
示例 2:
輸入:events = [[1,2,4],[3,4,3],[2,3,10]], k = 2
輸出:10
解釋:參加會議 2 ,得到價值和為 10 。
你沒法再參加別的會議了,因為跟會議 2 有重疊。你 不 需要參加滿 k 個會議。
示例 3:
輸入:events = [[1,1,1],[2,2,2],[3,3,3],[4,4,4]], k = 3
輸出:9
解釋:盡管會議互不重疊,你只能參加 3 個會議,所以選擇價值最大的 3 個會議。
**參數范圍:
1 <= k <= events.length
1 <= k * events.length <= 106
1 <= startDayi <= endDayi <= 109
1 <= valuei <= 106

分析

時間復雜度

時間復雜度O(nlogn+knlogn)。第一步時間復雜度O(nlogn),第二步時間復雜度O(klongn)。
第一步:收集結束時間,排序并除去重復。并給每個結束時間安排索引。
第二步:兩輪循環。

變量解釋

vEndTime結束時間升序并除去重復元素
mEndTimeToIndexs結束時間在vEndTime中的順序
vEndTimeIndexToMaxValuevEndTimeIndexToMaxValue[i]=j 表示,mEndTimeToIndexs[i]結束的會議的最大價值

注意

std::prev(it)之前不需要判斷,因為vEndTime中插入了一個比任何開始時間都小的數0。
每輪循環后,要確保vEndTimeIndexToMaxValue升序。

代碼

核心代碼

class Solution {
public:int maxValue(vector<vector<int>>& events, int k) {vector<int> vEndTime = { 0 };for (const auto& v : events){vEndTime.emplace_back(v[1]);}sort(vEndTime.begin(), vEndTime.end());vEndTime.erase(std::unique(vEndTime.begin(), vEndTime.end()), vEndTime.end());unordered_map<int, int> mEndTimeToIndexs;for (int i = 0; i < vEndTime.size(); i++){mEndTimeToIndexs[vEndTime[i]] = i;}vector<int> vEndTimeIndexToMaxValue(vEndTime.size());while (k--){vector<int> dp(vEndTime.size());for (const auto& v : events){int iEndIndex = mEndTimeToIndexs[v[1]];auto it = std::lower_bound(vEndTime.begin(), vEndTime.end(), v[0]);const int iMaxPreIndex = it - 1 - vEndTime.begin() ;const int iMaxValue = vEndTimeIndexToMaxValue[iMaxPreIndex] + v[2];dp[iEndIndex] = max(dp[iEndIndex],iMaxValue);}//使得dp升序int iPreMax = 0;for (auto& n : dp){n = max(n, iPreMax);iPreMax = max(n, iPreMax);}dp.swap(vEndTimeIndexToMaxValue);}return vEndTimeIndexToMaxValue.back();}
};

測試用例

template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
Assert(v1[i], v2[i]);
}
}

int main()
{
vector<vector> events;
int k;
int res;
{
Solution slu;
events = { {1,2,4},{3,4,3},{2,3,1} };
k = 2;
res = slu.maxValue(events, k);
Assert(res,7 );
}
{
Solution slu;
events = { {1,2,4},{3,4,3},{2,3,10} };
k = 2;
res = slu.maxValue(events, k);
Assert(res, 10);
}
{
Solution slu;
events = { {1,1,1},{2,2,2},{3,3,3},{4,4,4} };
k = 3;
res = slu.maxValue(events, k);
Assert(res, 9);
}

//CConsole::Out(res);

}

優化

代碼

class Solution {
public:int maxValue(vector<vector<int>>& events, int k) {vector<int> vEndTime = { 0 };for (const auto& v : events){vEndTime.emplace_back(v[1]);}sort(vEndTime.begin(), vEndTime.end());vEndTime.erase(std::unique(vEndTime.begin(), vEndTime.end()), vEndTime.end());unordered_map<int, int> mEndTimeToIndexs;for (int i = 0; i < vEndTime.size(); i++){mEndTimeToIndexs[vEndTime[i]] = i;}sort(events.begin(), events.end(), [](const auto& v0, const auto& v1) {return v0[0] < v1[0]; });vector<int> vEndTimeIndexToMaxValue(vEndTime.size());while (k--){vector<int> dp(vEndTime.size());int iPreMax = 0;int iPreIndex = 0;for (const auto& v : events){while ((iPreIndex < vEndTimeIndexToMaxValue.size()) && (vEndTime[iPreIndex] < v[0])){iPreMax = max(iPreMax, vEndTimeIndexToMaxValue[iPreIndex]);iPreIndex++;}int iEndIndex = mEndTimeToIndexs[v[1]];dp[iEndIndex] = max(dp[iEndIndex], iPreMax+v[2]);}dp.swap(vEndTimeIndexToMaxValue);			}return *std::max_element(vEndTimeIndexToMaxValue.begin(), vEndTimeIndexToMaxValue.end());}
};

時間復雜度

O(nk)

分析

將events通過開始時間排序后,就可以使用離線查詢。

sort(events.begin(), events.end(), [](const auto& v0, const auto& v1) {return v0[0] < v1[0]; });

iPreMax 記錄了所有結束時間比當前時間小的最大會議價值的最大值。

vEndTimeIndexToMaxValue[0,iPreIndex)的會議價值已經更新到iPreMax。 
while ((iPreIndex < vEndTimeIndexToMaxValue.size()) && (vEndTime[iPreIndex] < v[0])){iPreMax = max(iPreMax, vEndTimeIndexToMaxValue[iPreIndex]);iPreIndex++;}

注意: vEndTimeIndexToMaxValue不再升序,所以要:

return *std::max_element(vEndTimeIndexToMaxValue.begin(), vEndTimeIndexToMaxValue.end());

優化二:從開始時間大的處理

代碼

class Solution {
public:int maxValue(vector<vector<int>>& events, int k) {vector<int> vEndTime = { 0 };for (const auto& v : events){vEndTime.emplace_back(v[1]);}sort(vEndTime.begin(), vEndTime.end());vEndTime.erase(std::unique(vEndTime.begin(), vEndTime.end()), vEndTime.end());unordered_map<int, int> mEndTimeToIndexs;for (int i = 0; i < vEndTime.size(); i++){mEndTimeToIndexs[vEndTime[i]] = i;}sort(events.begin(), events.end(), [](const auto& v0, const auto& v1) {return v0[0] > v1[0]; });vector<int> vEndTimeIndexToMaxValue(vEndTime.size());while (k--){int iPreIndex = vEndTimeIndexToMaxValue.size()-1 ;for (const auto& v : events){while ((iPreIndex >=0 ) && (vEndTime[iPreIndex] >= v[0])){	iPreIndex--;}int iEndIndex = mEndTimeToIndexs[v[1]];vEndTimeIndexToMaxValue[iEndIndex] = max(vEndTimeIndexToMaxValue[iEndIndex], vEndTimeIndexToMaxValue[iPreIndex] +v[2]);}//使得dp升序int iPreMax = 0;for (auto& n : vEndTimeIndexToMaxValue){n = max(n, iPreMax);iPreMax = max(n, iPreMax);}}return *std::max_element(vEndTimeIndexToMaxValue.begin(), vEndTimeIndexToMaxValue.end());}
};

分析

時間復雜度O(kn)。

優點

不需要滾動向量,因為更新結束時間大的不會影響開始時間小的。

注意

一,開始時間降序排序。

 {return v0[0] > v1[0]; });

二,vEndTimeIndexToMaxValue必須保持升序。

擴展閱讀

視頻課程

有效學習:明確的目標 及時的反饋 拉伸區(難度合適),可以先學簡單的課程,請移步CSDN學院,聽白銀講師(也就是鄙人)的講解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成戰斗了,為老板分憂,請學習C#入職培訓、C++入職培訓等課程
https://edu.csdn.net/lecturer/6176

相關下載

想高屋建瓴的學習算法,請下載《喜缺全書算法冊》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想對大家說的話
聞缺陷則喜是一個美好的愿望,早發現問題,早修改問題,給老板節約錢。
子墨子言之:事無終始,無務多業。也就是我們常說的專業的人做專業的事。
如果程序是一條龍,那算法就是他的是睛

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165462.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165462.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165462.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

gitt開源項目的意義,公司為什么會對在gitt上有開源項目的人更大機會

Git是一種分布式版本控制系統&#xff0c;它可以幫助程序員管理代碼的歷史版本和協同工作。同時&#xff0c;Git也成為了開源項目的主要托管平臺之一。Git的開源項目意義重大&#xff0c;因為這種開源項目托管平臺可以幫助開發者將代碼和項目分享給全球的開發者&#xff0c;并且…

從0開始學習JavaScript--JavaScript元編程

JavaScript作為一門靈活的動態語言&#xff0c;具備強大的元編程能力。元編程是一種通過操作程序自身結構的編程方式&#xff0c;使得程序能夠在運行時動態地創建、修改、查詢自身的結構和行為。本文將深入探討JavaScript中元編程的各個方面&#xff0c;包括原型、反射、代理等…

2023亞太杯數學建模C題思路模型代碼

已完成C題思路代碼&#xff0c;文末名片獲取 C題是我們的一個數據分析問題&#xff0c;這個題目主要就是我們要去收集數據&#xff0c;清洗處理后進行分析。 問題1&#xff1a;分析影響中國新能源電動汽車發展的主要因素&#xff0c;建立數學模型&#xff0c;描述這些因素對中…

對未來新能源車測試工具的看法

汽車行業正在經歷變革的說法算是比較輕描淡寫的了&#xff0c;還記得我1983年加入這個行業時&#xff0c;行業聚焦點是引入發動機管理系統。當時還是以家庭掀背車為主的時代&#xff0c;發動機分析儀的體積像衣柜一樣大&#xff0c;還沒出現“CAN”通信協議。現在經常聽到我的導…

PHP預約上門回收廢品系統的代碼披露

PHP預約上門回收廢品系統的代碼披露 <?phpnamespace app\admin\controller;class Code {public function getTopDomainhuo(){error_reporting(0);$host $_SERVER["HTTP_HOST"];$matchstr "[^\\.]\\.(?:(" . $host . ")|\\w{2}|((" . $ho…

【第一部分:概述】ARM Realm Management Monitor specification

目錄 概述機密計算系統軟件組成MonitorRealmRealm Management Monitor (RMM)Virtual Machine (VM)HypervisorSecure Partition Manager (SPM)Trusted OS (TOS)Trusted Application (TA) Realm Management Monitor 參考文獻 概述 RMM是一個軟件組件&#xff0c;它構成了實現ARM…

機器學習筆記 - 復雜任務的CNN組合

基礎CNN架構可通過多種方式進行組合和擴展,從而解決更多、更復雜的任務。 1. 分類和定位 在分類和定位任務中,你不僅需要說出在圖像中找到的物體的類別,而且還需指出物體顯現在圖像中的邊界框坐標。這類任務假設在圖像中只有一個物體實例。 這個任務可通過在典型的分類網絡…

每日一題(LeetCode)----鏈表--兩數相加

每日一題(LeetCode)----鏈表–兩數相加 1.題目&#xff08;2. 兩數相加&#xff09; 給你兩個 非空 的鏈表&#xff0c;表示兩個非負的整數。它們每位數字都是按照 逆序 的方式存儲的&#xff0c;并且每個節點只能存儲 一位 數字。 請你將兩個數相加&#xff0c;并以相同形式返…

深入ReentrantReadWriteLock(一)

一、為什么要出現讀寫鎖 synchronized和ReentrantLock都是互斥鎖。 如果說有一個操作是讀多寫少的&#xff0c;還要保證線程安全的話。如果采用上述的兩種互斥鎖&#xff0c;效率方面很定是很低的。 在這種情況下&#xff0c;咱們就可以使用ReentrantReadWriteLock讀寫鎖去實現…

React16中打印事件對象取不到值的現象及其原因分析

React16中打印事件對象取不到值的現象及其原因分析 一、背景 在最近的開發過程中&#xff0c;遇到了一個看起來匪夷所思的問題?&#xff1a; <Inputplaceholder"請輸入"onChange{(e) > {console.log(e:, e)}}onKeyDown{handleKeyDown} />此時按理來說我…

旅行商問題(枚舉,回溯,動態規劃,貪心,分支界限)

文章目錄 問題描述暴力枚舉回溯法動態規劃法貪心法分支界限法 問題描述 假設有一個貨郎擔要拜訪n個城市&#xff0c;他必須選擇所要走的路程&#xff0c;路程的限制時每個城市只能拜訪一次&#xff0c;而且最后要走到原來出發的城市&#xff0c;要求路徑長度。 旅行商問題將要…

為銷售賦能:利用 Splashtop 增強遠程培訓技術

遠程銷售團隊這一概念在當今快節奏的商業環境中日益普遍。各公司正在計劃在不同地點靈活開展銷售業務&#xff0c;希望利用技術優勢縮小地域差距。但是&#xff0c;這種向遠程銷售的轉型面臨著重大挑戰&#xff0c;尤其在培訓和發展領域。培訓遠程銷售團隊需要采用創新方法&…

常見樹種(貴州省):012茶、花椒、八角、肉桂、杜仲、厚樸、枸杞、忍冬

摘要&#xff1a;本專欄樹種介紹圖片來源于PPBC中國植物圖像庫&#xff08;下附網址&#xff09;&#xff0c;本文整理僅做交流學習使用&#xff0c;同時便于查找&#xff0c;如有侵權請聯系刪除。 圖片網址&#xff1a;PPBC中國植物圖像庫——最大的植物分類圖片庫 一、茶 灌…

鴻蒙 ark ui 輪播圖實現教程

前言&#xff1a; 各位同學有段時間沒有見面 因為一直很忙所以就沒有去更新博客。最近有在學習這個鴻蒙的ark ui開發 因為鴻蒙不是發布了一個鴻蒙next的測試版本 明年會啟動純血鴻蒙應用 所以我就想提前給大家寫一些博客文章 效果圖 具體實現 我們在鴻蒙的ark ui 里面列表使…

土地利用數據技術服務

一、背景介紹 土地是人類賴以生存與發展的重要資源和物質保障&#xff0c;在“人口&#xff0d;資源&#xff0d;環境&#xff0d;發展&#xff08;PRED&#xff09;”復合系統 中&#xff0c;土地資源處于基礎地位。隨著現代社會人口的不斷增長以及工業化、城市化進程的加速&a…

Excel使用VLOOKUP查詢數據

VLOOKUP函數在百度百科中的解釋是&#xff1a; 解釋一下&#xff0c;函數需要4個參數&#xff1a; 參數1&#xff08;lookup_value&#xff09;&#xff1a;需要匹配的值參數2&#xff08;table_array&#xff09;&#xff1a;在哪個區域里進行匹配參數3&#xff08;col_index…

Dubbo3使用Zookeeper作為注冊中心的方案討論!詳解DubboAdmin與PrettyZoo來監控服務的優劣!

文章目錄 一&#xff1a;Dubbo注冊中心的基本使用 二&#xff1a;Zookeeper注冊中心的使用 1&#xff1a;依賴引入 2&#xff1a;實際開發 三&#xff1a;Zookeeper作為注冊中心的使用展示 1&#xff1a;啟動注冊Zookeeper服務 2&#xff1a;引入注冊中心 (一)&#xf…

Java 21增強對Emoji表情符號的處理了

現一個 Java 21 中有意思的東西&#xff01; 在java.Lang.Character類中增加了用于確定字符是否為 Emoji 表情符號的 API&#xff0c;主要包含下面六個新的靜態方法&#xff1a; public static boolean isEmoji(int codePoint) {return CharacterData.of(codePoint).isEmoji(…

操作系統 day13(RR、優先級調度)

RR&#xff08;時間片輪轉&#xff09; 響應時間&#xff1a;系統中有10個進程正在并發執行&#xff0c;如果時間片為1秒&#xff0c;則一個進程被響應可能需要等待9秒。也就是說&#xff0c;如果用戶在自己進程的時間片外通過鍵盤發出調試命令&#xff0c;可能需要等待9秒才能…