目錄
1 問題描述
中值問題是求一個n個數列表中某一數組下標k,它要求該下標元素比列表中的一半元素大,又比另一半元素小,這個中間的值被稱為中值。
選擇問題是求一個n個數列表的第k個最小元素的問題。
2 解決方案
2.1 計算中值問題
本文使用Lomuto划分算法思想,此處引用《算法設計與分析基礎》第三版上一段文字介紹及配圖,具體如下:
具體實現代碼如下:
package com.liuzhen.chapter4; public class MedianProblem { //Lomuto划分 /* * 參數A:給定的隨機數數組 * 參數start:開始進行選擇的數組元素位置 * 參數end:最后一個進行選擇的數組元素位置 * 函數功能:返回A[start]到A[end]元素中間的某一元素位置result,使得 左邊部分元素 < A[result] <=右邊部分元素 */ public int LomutoPartition(int[] A,int start,int end){ int begin = A[start]; int result = start; for(int i = start+1;i <= end;i++){ if(A[i] < begin){ /* * 一旦出現小於begin的元素,result向后移動一位; * 出現大於的不移動,當再次出現小於begin的元素,result向后移動一位, * 此時result恰好指向第一個大於begin的元素,此時執行swap(A,result,i) */ result = result + 1; swap(A,result,i); } } swap(A,start,result); return result; } //交換數組中位置為m和n上的元素值 public void swap(int[] A,int m,int n){ int temp = A[m]; A[m] = A[n]; A[n] = temp; } public static void main(String[] args){ MedianProblem test = new MedianProblem(); int[] A = {4,1,10,8,7,12,9,2,15}; int result = test.LomutoPartition(A, 0, A.length-1); System.out.println("對數組進棧Lomuto划分后結果:"); for(int i = 0;i < A.length;i++) System.out.print(A[i]+" "); System.out.println("\n"+"進行Lomuto划分后的數組中軸位置:"+result); } }
運行結果:
對數組進棧Lomuto划分后結果: 2 1 4 8 7 12 9 10 15 進行Lomuto划分后的數組中軸位置:2
2.2 選擇問題
通過2.1 計算中值問題中Lomuto算法的運用,那么如何尋找n個元素中第k個最小元素呢?此處調用2.1中相關函數,具體實現代碼如下:
package com.liuzhen.chapter4; public class SelectProblem { //快速選擇 /* * 參數A:給定隨機數數組 * 參數k:要求輸出的第k個最小元素 * 函數功能:返回數組A的第k個最小元素的值 */ public int quickSelect(int[] A,int k){ int start = 0; int end = A.length-1; int mid = new MedianProblem().LomutoPartition(A, start,end); while(true){ if(mid > k-1){ end = mid-1; mid = new MedianProblem().LomutoPartition(A, start,end); } else if(mid < k-1){ start = mid+1; mid = new MedianProblem().LomutoPartition(A, start,end); } else break; } return A[mid]; } public static void main(String[] args){ SelectProblem test = new SelectProblem(); int[] A = {4,1,10,8,7,12,9,2,15}; int result = test.quickSelect(A, 5); System.out.println("對數組進行快速選擇並執行划分后結果:"); for(int i = 0;i < A.length;i++) System.out.print(A[i]+" "); System.out.println("\n"+"進行快速選擇后得到數組第5最小元素(從小到大排序):"+result); } }
運行結果:
對數組進行快速選擇並執行划分后結果: 2 1 4 7 8 12 9 10 15 進行快速選擇后得到數組第5最小元素(從小到大排序):8