1. 程式人生 > >LintCode#80FindMedian(利用快排找中位數)

LintCode#80FindMedian(利用快排找中位數)

  • 題目:用時間複雜度為o(nlogn)的演算法,給定一個未排序的整數陣列,找到其中位數。中位數是排序後陣列的中間值,如果陣列的個數是偶數個,則返回排序後陣列的第N/2個數。
  • 難度:Easy
  • 思路:利用快排,pivot存放的位置index,如果index=(N-1)/2,說明pivot前面有index個元素小於或者pivot,每次遞迴快排,判斷index的值與(N-1)/2的大小關係
  • 程式碼:
    這裡的快排是直接用陣列待排序的陣列序列的第一個元素作為樞紐元素
public class Solution {
    /**
     * @param nums: A list of integers.
     * @return
: An integer denotes the middle number of the array. */
public int median(int[] nums) { // write your code here if(nums == null || nums.length == 0){ return 0; } int len = nums.length; if(len == 1){ return nums[0]; } return
quickSort(nums, 0, len-1); } public int quickSort(int[] nums, int start, int end){ int pivot = nums[start];//取陣列中第一個元素為樞紐 int i = start; int j = end; if(start < end){ while(i < j){ System.out.println(i + "-" + j); while(i < end && nums[i] <= pivot){ i++; } while
(j > start && nums[j] >= pivot){ j--; } if(i < j){ int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; }else{ break; } } if(pivot > nums[j]){ nums[start] = nums[j]; nums[j] = pivot; }//這裡的交換,需要先判斷pivot和nums[j]的大小(因為樞紐元素是start位置,所以需要與j位置的進行判斷並交換) //找到pivot存在的位置j,這裡是j位置作為樞紐的存放位置,所以判斷j與(N-1)/2的大小關係 if(j == (nums.length-1)/2){ return nums[j]; }else if(j < (nums.length-1)/2){ return quickSort(nums, j+1, end); }else{ return quickSort(nums, start, j-1); } }else{ return nums[start]; } } }

這一道題目,讓我對快排又有了重新的認識,以前看書上快排的虛擬碼,覺得理解得很好了,但是這次用快排來解決問題的時候,自己手寫快排,發現快排遠不止我想象的簡單。
值得注意的細節有:

  1. 樞紐元素的位置選擇,直接影響後面進行樞紐元素在陣列中的最終位置

    • 題目中我選擇的樞紐元素位置是待排序序列的首部,那最後進行比較並且交換的位置就是j位置
    • 書上給的虛擬碼,樞紐元素位置是在待排序序列的倒數第二個,然後用i位置的值和樞紐比較並且交換

    這一步是將樞紐元素在陣列中的位置確定

  2. 繼續下一次快排呼叫中的start位置和end位置的確定

    • 如果第1點中,與樞紐元素交換的是j位置的值,那麼就以j為分界,將陣列分為兩部分進行快排