算法筆記_031:計算中值和選擇問題(Java)


目錄

1 問題描述 

2 解決方案

2.1 計算中值問題

2.2 選擇問題

 


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

 


免責聲明!

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



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