為什么基於快排的查找第k大數時間復雜度是O(n)


我們都知道,查找第k大數有一個很常用的方法,是基於快排的查找,思路跟快排基本一樣,代碼如下:

    public int findKthLargest(int[] nums, int k) {
        return (findKthNum(nums,0,nums.length-1,k-1));
    }

    private int findKthNum(int[] nums, int left, int right, int k){
        int stan = nums[right];
        int i = left, j = right;
        if (left == right && left == k) {
            return nums[left];
        }
        else {
            while (i < j) {
                while (i < j && nums[i] >= stan) {
                    i++;
                }
                while (i < j && nums[j] <= stan){
                    j--;
                }
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
        nums[right] = nums[i];
        nums[i] = stan;
        if (k < i) {
            return findKthNum(nums, left, i - 1, k);
        }
        else if (k > i) {
            return findKthNum(nums, i + 1, right, k);
        }
        else {
            return nums[i];
        }
    }

因為每次分割完只需要繼續操作一邊,所以時間復雜度是O(n)。

但光是這樣解釋讓人有點不清楚,不通過計算很難讓人明白為什么是O(n),比如,即便每次只操作一邊,那么遍歷的次數也是logn次,每次遍歷是O(n),很容易讓人誤解為該方法是O(nlogn)。

所以這里還是要回到時間復雜度專門的遞推公式上來。

我們都知道,快速排序的理想以及平均時間復雜度是O(nlogn),其遞推公式如下,跟歸並排序基本無異,只是多了一個在理想或者平均的限制,因為快排的最壞是O(n^2)

平均情況下:T(n)=2*T(n/2)+n;      第一次划分

      =2*(2*T(n/4)+n/2)+n;     第二次划分  (=2^2*T(n/4)+2*n)

      =2*(2*(2*T(n/8)+n/4)+n/2)+n;     第三次划分(=2*3*T(n/8)+3*n)

      =.....................

      =2^m+m*n;  第m次划分

因為2^m=n,所以等價於 = n+m*n
所以m=logn,所以T(n)=n+n*logn;     

這邊還是比較好理解的,那么基於快排的查找第k大數的時間復雜度如下:

平均情況下:T(n) = T(n/2) + n;      第一次划分

      = T(n/4) + n/2 + n;     第二次划分  

      = T(n/8) + n/4 +n/2 +n;     第三次划分

      =.....................

      = T(n/n) + 2 + 4 + ... + n;  第m次划分

是一個等比數列的求和公式,那么顯然T(n) = 2n

所以計算時間復雜度最好嚴謹按照遞推公式來,那么這里注意基於快排查找第k大數,也是平均時間復雜度為O(n)。

《算法導論》介紹到一個最壞情況下也是O(n)的方法,這里不做詳細介紹,參考http://blog.chinaunix.net/uid-26456800-id-3407406.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM