分享一道有趣的 Leetcode 題目

Remember發表於2019-11-16

分享一道有趣的 Leetcode 題目

開篇

今天日常刷題的時候,依舊選擇 tagBinary Serach 型別的題目。這還是道熱門的題目,看點贊數就知道了。

分享一道有趣的Leetcode題目

題目介紹

給定一個 N*N 的矩陣(這麼正經的翻譯你一定不喜歡,所以你直接理解成二維陣列就行了)。它的每行和每列都按照升序排序,問題是,通過一個給定的數值 K,找出這個二維陣列中第 K 小的數。

先說下我最初的想法,這個題目歸別到 Binary Serach,那就肯定是可以用二分的思想的,但是按照我之前刷的二分題目,就算獲取到中位數,我也並不能確定這個中位數的位置大小排在陣列的整體大小位置,我只能確定我這一行的位置,我也只知道我當前位置的上一行對應的列比我小而已。

題目分析

之所以這樣想,是我潛意思裡都把二維結構+二分查詢,對應的中位數預設理解為就是索引位置。跳出這個思維空間再思考,查詢二維陣列中第 K 小的數那必然存在於二維陣列當中啊。調整思路。開始二分模板解題。之前寫過一篇而二分的文章)

left 初始值即陣列最小值 $left=$matrix[0][0],right 初始值即陣列最大值 $right=$matrix[行數-1][列數-1];

開始往中間擠壓。先求得中位數。這個的中位數指的是具體的值,而不是索引位置的意思。只要統計這個二維陣列中小於等於當前中位數的個數。如果統計的個數小於給定值 K,說明第 K 小的值並不在 left 和 中位數之間,而是在中位數+1 至 right 之間,所以重新賦值 left (不包括中位數) ,否則的話賦值 right。最後隨意返回 left 或者 right

上程式碼

/**
     * @param Integer[][] $matrix
     * @param Integer $k
     * @return Integer
     */
    function kthSmallest($matrix, $k)
    {
        $row = count($matrix);
        $col = count($matrix[0]);
        $left = $matrix[0][0];
        $right = $matrix[$row - 1][$col - 1];

        while ($left < $right) {
            $middle = ($left + $right) >> 1;
            $count = $this->lessMiddleAmount($matrix, $middle, $row - 1, $col);
            if ($count < $k) {
                $left = $middle + 1;
            } else {
                $right = $middle;
            }
        }
        return $left;
    }

    function lessMiddleAmount($matrix, $middle, $row, $col)
    {
        $left = 0;
        $count = 0;
        while ($row >= 0 && $left < $col) {
            if ($matrix[$row][$left] <= $middle) {
                $count += $row + 1;
                $left++;
            } else {
                $row--;
            }
        }
        return $count;
    }

結尾

上面 left 為什麼不包括中位數?可以從兩個角度分析,按照邏輯思維的角度,既然統計小於等於中位數的個數都比 K 小,我還咋麼去爭取當上第 K 小的數??? 另一角度,從當前執行的程式上來分析,獲取的中位數我習慣這樣寫 ($left+$right)>>1 ,如果 left + right 是奇數的情況下並沒有爭議,如果是偶數呢?那麼我這裡將得到一個左中位數。程式往下面走,如果走的是 if($count<$k) 這個分支的話,並且我的 $left 包含了中位數,會發生什麼?答案很明顯,程式進入死迴圈。直至你收到一個 Time Limit Exceeded 的錯誤。

執行結果也是妥妥的 AC。(千萬別相信這個執行效率,都是騙人的?)

分享一道有趣的Leetcode題目

吳親庫裡

相關文章