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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

根据身高重建队列

發布時間:2024/4/18 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 根据身高重建队列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

思路

本題有兩個維度,h和k,看到這種題目一定要想如何確定一個維度,然后在按照另一個維度重新排列。

其實如果大家認真做了貪心算法:分發糖果,就會發現和此題有點點的像。

在貪心算法:分發糖果的時候說過遇到兩個維度權衡的時候,一定要先確定一個維度,再確定另一個維度。

「如果兩個維度一起考慮一定會顧此失彼」。

對于本題令人困惑的點是先確定k還是先確定h呢,也就是究竟先按h排序呢,還先按照k排序呢?

如果按照k來從小到大排序,排完之后,會發現k的排列并不符合條件,身高也不符合條件,兩個維度哪一個都沒確定下來。

那么按照身高h來排序呢,身高一定是從大到小排(身高相同的話則k小的站前面),讓高個子在前面。

「此時我們可以確定一個維度了,就是身高,前面的節點一定都比本節點高!」

那么只需要按照k為下標重新插入隊列就可以了,為什么呢?

以圖中{5,2} 為例:


按照身高排序之后,優先按身高高的people的k來插入,后序插入節點也不會影響前面已經插入的節點,最終按照k的規則完成了隊列。

所以在按照身高從大到小排序后:

「局部最優:優先按身高高的people的k來插入。插入操作過后的people滿足隊列屬性」

「全局最優:最后都做完插入操作,整個隊列滿足題目隊列屬性」

局部最優可推出全局最優,找不出反例,那就試試貪心。

回歸本題,整個插入過程如下:

排序完的people:
[[7,0], [7,1], [6,1], [5,0], [5,2],[4,4]]

插入的過程:插入[7,0]:[[7,0]]
插入[7,1]:[[7,0],[7,1]]
插入[6,1]:[[7,0],[6,1],[7,1]]
插入[5,0]:[[5,0],[7,0],[6,1],[7,1]]
插入[5,2]:[[5,0],[7,0],[5,2],[6,1],[7,1]]
插入[4,4]:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]

此時就按照題目的要求完成了重新排列。

時間復雜度O(nlogn + n^3) 空間復雜度O(n) class Solution { public:static bool cmp(vector<int> a,vector<int> b){if(a[0]==b[0]) return a[1]<b[1]; //身高相同的,返回下標小的,升序排列else return a[0]>b[0];//否則按身高降序排列//要點看比較符號<表明要升序排列,>表示要降序排列}vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {sort(people.begin(),people.end(),cmp);vector<vector<int>> que;for(int ii=0;ii<people.size();ii++){int position=people[ii][1];que.insert(que.begin()+position,people[ii]);} return que;} };

n^3 是怎么來的?

數組中插入元素和刪除元素都是O(n^2)的復雜度。

我們就是要模擬一個插入隊列的行為,所以不應該使用數組,而是要使用鏈表!

鏈表的插入操作復雜度是O(n):尋找插入元素位置O(n),插入元素O(1)。

可以看出使用鏈表的插入效率要比普通數組高出一個數量級!

// 版本二 時間復雜度O(nlogn + n^2) 空間復雜度O(n) class Solution { public:// 身高從大到小排(身高相同k小的站前面)static bool cmp(const vector<int> a, const vector<int> b) {if (a[0] == b[0]) return a[1] < b[1];return a[0] > b[0];}vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {sort (people.begin(), people.end(), cmp);list<vector<int>> que; // list底層是鏈表實現,插入效率比vector高的多for (int i = 0; i < people.size(); i++) {int position = people[i][1]; // 插入到下標為position的位置std::list<vector<int>>::iterator it = que.begin();while (position--) { // 尋找在插入位置it++; }que.insert(it, people[i]); }return vector<vector<int>>(que.begin(), que.end());} };

總結

關于出現兩個維度一起考慮的情況,我們已經做過兩道題目了,另一道就是貪心算法:分發糖果。

「其技巧都是確定一邊然后貪心另一邊,兩邊一起考慮,就會顧此失彼」。

這道題目可以說比貪心算法:分發糖果難不少,其貪心的策略也是比較巧妙。

最后我給出了兩個版本的代碼,可以明顯看是使用C++中的list(底層鏈表實現)比vector(數組)效率高得多。

「對使用某一種語言容器的使用,特性的選擇都會不同程度上影響效率」。

總結

以上是生活随笔為你收集整理的根据身高重建队列的全部內容,希望文章能夠幫你解決所遇到的問題。

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