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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

根据身高重建队列

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

思路

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

其實(shí)如果大家認(rèn)真做了貪心算法:分發(fā)糖果,就會(huì)發(fā)現(xiàn)和此題有點(diǎn)點(diǎn)的像。

在貪心算法:分發(fā)糖果的時(shí)候說過遇到兩個(gè)維度權(quán)衡的時(shí)候,一定要先確定一個(gè)維度,再確定另一個(gè)維度。

「如果兩個(gè)維度一起考慮一定會(huì)顧此失彼」。

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

如果按照k來從小到大排序,排完之后,會(huì)發(fā)現(xiàn)k的排列并不符合條件,身高也不符合條件,兩個(gè)維度哪一個(gè)都沒確定下來。

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

「此時(shí)我們可以確定一個(gè)維度了,就是身高,前面的節(jié)點(diǎn)一定都比本節(jié)點(diǎn)高!」

那么只需要按照k為下標(biāo)重新插入隊(duì)列就可以了,為什么呢?

以圖中{5,2} 為例:


按照身高排序之后,優(yōu)先按身高高的people的k來插入,后序插入節(jié)點(diǎn)也不會(huì)影響前面已經(jīng)插入的節(jié)點(diǎn),最終按照k的規(guī)則完成了隊(duì)列。

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

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

「全局最優(yōu):最后都做完插入操作,整個(gè)隊(duì)列滿足題目隊(duì)列屬性」

局部最優(yōu)可推出全局最優(yōu),找不出反例,那就試試貪心。

回歸本題,整個(gè)插入過程如下:

排序完的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]]

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

時(shí)間復(fù)雜度O(nlogn + n^3) 空間復(fù)雜度O(n) class Solution { public:static bool cmp(vector<int> a,vector<int> b){if(a[0]==b[0]) return a[1]<b[1]; //身高相同的,返回下標(biāo)小的,升序排列else return a[0]>b[0];//否則按身高降序排列//要點(diǎn)看比較符號(hào)<表明要升序排列,>表示要降序排列}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 是怎么來的?

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

我們就是要模擬一個(gè)插入隊(duì)列的行為,所以不應(yīng)該使用數(shù)組,而是要使用鏈表!

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

可以看出使用鏈表的插入效率要比普通數(shù)組高出一個(gè)數(shù)量級(jí)!

// 版本二 時(shí)間復(fù)雜度O(nlogn + n^2) 空間復(fù)雜度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底層是鏈表實(shí)現(xiàn),插入效率比vector高的多for (int i = 0; i < people.size(); i++) {int position = people[i][1]; // 插入到下標(biāo)為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());} };

總結(jié)

關(guān)于出現(xiàn)兩個(gè)維度一起考慮的情況,我們已經(jīng)做過兩道題目了,另一道就是貪心算法:分發(fā)糖果。

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

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

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

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

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。