1. 程式人生 > 程式設計 >小程式實現上下切換位置

小程式實現上下切換位置

根據身高重建佇列

假設有打亂順序的一群人站成一個佇列。 每個人由一個整數對(h, k)表示,其中h是這個人的身高,k是排在這個人前面且身高大於或等於h的人數。 編寫一個演算法來重建這個佇列。

注意:
總人數少於1100人。

示例

輸入:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

輸出:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]

題解

/**
 * @param {number[][]} people
 * @return {number[][]}
 */
var reconstructQueue = function(people) {
    // people.sort((a, b) => a[0] === b[0] ? b[1] - a[1] : a[0] - b[0]);
    people.sort((a, b) => a[0] - b[0]);
    const n = people.length;
    let target = [];
    people.forEach((v) => {
        let spaces = v[1] + 1;
        for(let i=0;i<n;++i){
            if(target[i] === void 0 || target[i][0] === v[0]){
                spaces--;
                if(spaces <= 0 && target[i] === void 0){
                    target[i] = v;
                    break;
                }
            }
        }
    })
    return target;
};

思路

當每個人的身高都不相同時,我們將他們按照身高從小到大進行排序,之後使用插入的方式進行還原,首先我們假設有n個人,然年後我們將要插入第i個人,現在第0 ... i-1已經排好了位置,無論他們如何站隊,對我們將要插入的第i個人都沒有影響,對於第i ... n-1個人,只要插入的位置在第i個人前,就能夠對第i個人產生影響,之後我們就可以建立一個長度為n的陣列,對排序過後的陣列將其分別插入,那麼當我們插入第i個人時,其要插入的位置必定是其高度大於它的數量+1,例如我們第一個要插入的是(5, 2),那麼他的位置就是<empty>, <empty>, (5, 2),也就是說給他安排的空位是第三個位置,此外由於其是佇列的第一個數值,其後的值必定比他大,所以其後的值按照同樣的規則進行插入是可以滿足條件的,在這裡需要特殊處理一下身高相同的人,如果身高相同,同樣應該將其作為一個空位去處理,之後特殊處理這個位置如果是空位則直接插入,否則插入到其後邊的位置。在官方給出的題解是在排序的時候根據身高升序,在根據前邊身高高於他的人的數量進行降序,之後就可以直接進行上述規則而不用特殊處理相等的情況,舉個例子,當我們根據上述的排序規則進行排序後得到(5, 2) (5, 0) ...

,那麼先插入(5, 2),再插入(5, 0)可以得到(5, 0), <empty>, (5, 2),當然我們經過特殊處理相同的情況也是可以得到的,但是如果不經過特殊處理則會得到(5, 0), <empty>, <empty>, (5, 2)顯然是不合適的。首先進行排序,這裡只是按照身高進行排序,之後取得陣列長度n,定義目標陣列,遍歷排序過後的陣列,定義好應該取得的空位置並+1,之後進行n次迴圈,如果這個位置未定義或者值與要插入的值相同,那麼就將應該減少的空位置數量-1,如果應該置入的空位置數量小於0並且這個位置是空,那麼就將該值插入該位置並結束內層迴圈,最後返回目標陣列即可。

每日一題

https://github.com/WindrunnerMax/EveryDay

參考

https://leetcode-cn.com/problems/queue-reconstruction-by-height/