1. 程式人生 > 實用技巧 >【LeetCode/LintCode】 題解丨阿里巴巴面試題:第k大元素

【LeetCode/LintCode】 題解丨阿里巴巴面試題:第k大元素

在陣列中找到第 k 大的元素。(你可以交換陣列中的元素的位置)

線上評測地址:點選此處前往

樣例 1:

輸入:
n = 1, nums = [1,3,4,2]
輸出:
4

樣例 2:

輸入:
n = 3, nums = [9,3,2,4,8]
輸出:
4

【題解】

演算法:快速選擇演算法

最容易想到的就是直接排序,返回第k大的值。時間複雜度是O(nlogn),這裡提供O(n)的解法。

這題其實是快速排序演算法的變體,在九章演算法班中也有詳細講解。通過快速排序演算法的partition步驟,可以將小於pivot的值劃分到pivot左邊,大於pivot的值劃分到pivot右邊,所以可以直接得到pivot的rank。從而縮小範圍繼續找第k大的值。

partition步驟:

  1. 令left = start,right = end,pivot = nums[left]。
  2. 當nums[left] < pivot時,left指標向右移動。
  3. 當nums[right] > pivot時,right指標向左移動。
  4. 交換兩個位置的值,right指標左移,left指標右移。
  5. 直到兩指標相遇,否則回到第2步。

每次partition後根據pivot的位置,尋找下一個搜尋的範圍。

複雜度分析

設陣列長度為n

時間複雜度O(n)

  • 對一個數組進行partition的時間複雜度為O(n)。
  • 分治,選擇一邊繼續進行partition。
  • 所以總的複雜度為T(n) = T(n / 2) + O(n),總時間複雜度依然為O(n)。

空間複雜度O(1)

  • 只需要快速選擇遊標的O(1)額外空間。
 public class Solution {
    /**
     * @param n: An integer
     * @param nums: An array
     * @return: the Kth largest element
     */
    public int kthLargestElement(int k, int[] nums) {
        int n = nums.length;
        // 為了方便編寫程式碼,這裡將第 k 大轉換成第 k 小問題。
        k = n - k;
        return partition(nums, 0, n - 1, k);
    }
    public int partition(int[] nums, int start, int end, int k) {
        int left = start, right = end;
        int pivot = nums[left];
        
        while (left <= right) {
            while (left <= right && nums[left] < pivot) {
                left++;
            }
            while (left <= right && nums[right] > pivot) {
                right--;
            }
            if (left <= right) {
                swap(nums, left, right);
                left++;
                right--;
            }
        }
        
        // 如果第 k 小在右側,搜尋右邊的範圍,否則搜尋左側。
        if (k <= right) {
            return partition(nums, start, right, k);
        }
        if (k >= left) {
            return partition(nums, left, end, k);
        }
        return nums[k];
    }
    public void swap(int[] nums, int x, int y) {
        int temp = nums[x];
        nums[x] = nums[y];
        nums[y] = temp;
    }
}

更多題解參見:九章演算法官網