<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ?LeetCode刷題實戰(zhàn)406:根據(jù)身高重建隊列

          共 4168字,需瀏覽 9分鐘

           ·

          2021-10-12 23:51

          算法的重要性,我就不多說了吧,想去大廠,就必須要經(jīng)過基礎(chǔ)知識和業(yè)務(wù)邏輯面試+算法面試。所以,為了提高大家的算法能力,這個公眾號后續(xù)每天帶大家做一道算法題,題目就從LeetCode上面選 !

          今天和大家聊的問題叫做?根據(jù)身高重建隊列,我們先來看題面:
          https://leetcode-cn.com/problems/queue-reconstruction-by-height/

          You are given an array of people, people, which are the attributes of some people in a queue (not necessarily in order). Each people[i] = [hi, ki] represents the ith person of height hi with exactly ki other people in front who have a height greater than or equal to hi.
          Reconstruct and return the queue that is represented by the input array people. The returned queue should be formatted as an array queue, where queue[j] = [hj, kj] is the attributes of the jth person in the queue (queue[0] is the person at the front of the queue).

          假設(shè)有打亂順序的一群人站成一個隊列,數(shù)組 people 表示隊列中一些人的屬性(不一定按順序)。每個 people[i] = [hi, ki] 表示第 i 個人的身高為 hi ,前面 正好 有 ki 個身高大于或等于 hi 的人。

          請你重新構(gòu)造并返回輸入數(shù)組 people 所表示的隊列。返回的隊列應(yīng)該格式化為數(shù)組 queue ,其中 queue[j] = [hj, kj] 是隊列中第 j 個人的屬性(queue[0] 是排在隊列前面的人)。

          示例

          示例 1:
          輸入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
          輸出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
          解釋:
          編號為 0 的人身高為 5 ,沒有身高更高或者相同的人排在他前面。
          編號為 1 的人身高為 7 ,沒有身高更高或者相同的人排在他前面。
          編號為 2 的人身高為 5 ,有 2 個身高更高或者相同的人排在他前面,即編號為 0 和 1 的人。
          編號為 3 的人身高為 6 ,有 1 個身高更高或者相同的人排在他前面,即編號為 1 的人。
          編號為 4 的人身高為 4 ,有 4 個身高更高或者相同的人排在他前面,即編號為 0、1、2、3 的人。
          編號為 5 的人身高為 7 ,有 1 個身高更高或者相同的人排在他前面,即編號為 1 的人。
          因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新構(gòu)造后的隊列。

          示例 2:
          輸入:people = [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]]
          輸出:[[4,0],[5,0],[2,2],[3,2],[1,4],[6,0]]


          解題

          https://www.shangmayuan.com/a/08810c8da0fb4381a83a0a22.html


          本題有兩個維度,h和k,看到這種題目必定要想如何肯定一個維度,而后在按照另外一個維度從新排列。

          其實若是你們認真作了貪心算法:分發(fā)糖果,就會發(fā)現(xiàn)和此題有點點的像。ide

          在貪心算法:分發(fā)糖果我就強調(diào)過一次,遇到兩個維度權(quán)衡的時候,必定要先肯定一個維度,再肯定另外一個維度。優(yōu)化

          「若是兩個維度一塊兒考慮必定會顧此失彼」。

          對于本題相信你們困惑的點是先肯定k仍是先肯定h呢,也就是究竟先按h排序呢,還先按照k排序呢?

          若是按照k來從小到大排序,排完以后,會發(fā)現(xiàn)k的排列并不符合條件,身高也不符合條件,兩個維度哪個都沒肯定下來。

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

          「此時咱們能夠肯定一個維度了,就是身高,前面的節(jié)點必定都比本節(jié)點高!」

          那么只須要按照k為下標從新插入隊列就能夠了,為何呢?

          以圖中{5,2} 為例:


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

          因此在按照身高從大到小排序后:

          「局部最優(yōu):優(yōu)先按身高高的people的k來插入。插入操做事后的people知足隊列屬性」

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

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

          一些同窗可能也會疑惑,你怎么知道局部最優(yōu)就能夠推出全局最優(yōu)呢?有數(shù)學證實么?

          在貪心系列開篇詞關(guān)于貪心算法,你該了解這些!中,我已經(jīng)講過了這個問題了。

          刷題或者面試的時候,手動模擬一下感受能夠局部最優(yōu)推出總體最優(yōu),并且想不到反例,那么就試一試貪心,至于嚴格的數(shù)學證實,就不在討論范圍內(nèi)了。

          若是沒有讀過關(guān)于貪心算法,你該了解這些!的同窗建議讀一下,相信對貪心就有初步的了解了。

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

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

          此時就按照題目的要求完成了從新排列。
          C++代碼以下:


          // 版本一
          class?Solution?{
          public:
          ????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);
          ????????vector<vector<int>> que;
          ????????for?(int?i = 0; i < people.size(); i++) {
          ????????????int?position = people[i][1];
          ????????????que.insert(que.begin() + position, people[i]);
          ????????}
          ????????return?que;
          ????}
          };


          但使用vector是很是費時的,C++中vector(能夠理解是一個動態(tài)數(shù)組,底層是普通數(shù)組實現(xiàn)的)若是插入元素大于預(yù)先普通數(shù)組大小,vector底部會有一個擴容的操做,即申請兩倍于原先普通數(shù)組的大小,而后把數(shù)據(jù)拷貝到另外一個更大的數(shù)組上。

          因此使用vector(動態(tài)數(shù)組)來insert,是費時的,插入再拷貝的話,單純一個插入的操做就是O(n^2)了,甚至可能拷貝好幾回,就不止O(n^2)了。

          改為鏈表以后,C++代碼以下:

          // 版本二
          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底層是鏈表實現(xiàn),插入效率比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());
          ????}
          };


          好了,今天的文章就到這里,如果覺得有所收獲,請順手點個在看或者轉(zhuǎn)發(fā)吧,你們的支持是我最大的動力 。

          上期推文:

          LeetCode1-400題匯總,希望對你有點幫助!

          LeetCode刷題實戰(zhàn)401:二進制手表

          LeetCode刷題實戰(zhàn)402:移掉 K 位數(shù)字

          LeetCode刷題實戰(zhàn)403:青蛙過河

          LeetCode刷題實戰(zhàn)404:左葉子之和

          LeetCode刷題實戰(zhàn)405:數(shù)字轉(zhuǎn)換為十六進制數(shù)


          瀏覽 43
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美色18在线 | 国产精品久久久久久久久毛毛 | 黄色a一级直播 | 7777久久| 无码日韩人妻精品久久蜜桃 |