<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理
       
        javaeye的一個帖子介紹一道面試題,取數(shù)組的最大元素和前n個大元素,取最大元素很簡單,遍歷即可。取前N大元素,可以利用排序,最簡單的實現(xiàn):

        public static int[] findTopNValues(int[] anyOldOrderValues, int n) {
            Arrays.sort(anyOldOrderValues);
            
    int[] result = new int[n];
            System.arraycopy(anyOldOrderValues, anyOldOrderValues.length 
    - n,
                    result, 
    0, n);
            
    return result;
        }
       
         Arrays.sort(int[])使用的是快排,平均的時間復(fù)雜度是O( n lg(n)),在一般情況下已經(jīng)足夠好。那么有沒有平均情況下O(n)復(fù)雜度的算法?這個還是有的,這道題目其實是選擇算法的變形,選擇一個數(shù)組中的第n大元素,可以采用類似快排的方式劃分數(shù)組,然后只要在一個子段做遞歸查找就可以,平均狀況下可以做到O(n)的時間復(fù)雜度,對于這道題來說稍微變形下算法即可解決:

        /**
         * 求數(shù)組的前n個元素
         * 
         * 
    @param anyOldOrderValues
         * 
    @param n
         * 
    @return
         
    */
        
    public static int[] findTopNValues(int[] anyOldOrderValues, int n) {
            
    int[] result = new int[n];
            findTopNValues(anyOldOrderValues, 
    0, anyOldOrderValues.length - 1, n,
                    n, result);
            
    return result;
        }

        
    public static final void findTopNValues(int[] a, int p, int r, int i,
                
    int n, int[] result) {
            
    // 全部取到,直接返回
            if (i == 0)
                
    return;
            
    // 只剩一個元素,拷貝到目標數(shù)組
            if (p == r) {
                System.arraycopy(a, p, result, n 
    - i, i);
                
    return;
            }
            
    int len = r - p + 1;
            
    if (i > len || i < 0)
                
    throw new IllegalArgumentException();
            
    // if (len < 7) {
            
    // Arrays.sort(a, p, r+1);
            
    // System.arraycopy(a, r - i+1 , result, n - i, i);
            
    // return;
            
    // }

            
    // 劃分
            int q = medPartition(a, p, r);
            
    // 計算右子段長度
            int k = r - q + 1;
            
    // 右子段長度恰好等于i
            if (i == k) {
                
    // 拷貝右子段到結(jié)果數(shù)組,返回
                System.arraycopy(a, q, result, n - i, i);
                
    return;
            } 
    else if (k > i) {
                
    // 右子段比i長,遞歸到右子段求前i個元素
                findTopNValues(a, q + 1, r, i, n, result);
            } 
    else {
                
    // 右子段比i短,拷貝右子段到結(jié)果數(shù)組,遞歸左子段求前i-k個元素
                System.arraycopy(a, q, result, n - i, k);
                findTopNValues(a, p, q 
    - 1, i - k, n, result);
            }
        }

        
    public static int medPartition(int x[], int p, int r) {
            
    int len = r - p + 1;
            
    int m = p + (len >> 1);
            
    if (len > 7) {
                
    int l = p;
                
    int n = r;
                
    if (len > 40) { // Big arrays, pseudomedian of 9
                    int s = len / 8;
                    l 
    = med3(x, l, l + s, l + 2 * s);
                    m 
    = med3(x, m - s, m, m + s);
                    n 
    = med3(x, n - 2 * s, n - s, n);
                }
                m 
    = med3(x, l, m, n); // Mid-size, med of 3
            }
            
    if (m != r) {
                
    int temp = x[m];
                x[m] 
    = x[r];
                x[r] 
    = temp;
            }
            
    return partition(x, p, r);
        }

        
    private static int med3(int x[], int a, int b, int c) {
            
    return x[a] < x[b] ? (x[b] < x[c] ? b : x[a] < x[c] ? c : a)
                    : x[b] 
    > x[c] ? b : x[a] > x[c] ? c : a;
        }

        
    public static void swap(int[] a, int i, int j) {
            
    int temp = a[i];
            a[i] 
    = a[j];
            a[j] 
    = temp;
        }

        
    public static int partition(int a[], int p, int r) {
            
    int x = a[r];
            
    int m = p - 1;
            
    int j = r;
            
    while (true) {
                
    do {
                    j
    --;
                } 
    while (j>=p&&a[j] > x);
                
    do {
                    m
    ++;
                } 
    while (a[m] < x);
                
                
    if (j < m)
                    
    break;
                swap(a, m, j);
            }
            swap(a, r, j 
    + 1);
            
    return j + 1;
        }
     選擇算法還有最壞情況下O(n)復(fù)雜度的實現(xiàn),有興趣可以讀算法導(dǎo)論和維基百科。題外,我測試了下這兩個實現(xiàn),在我的機器上大概有2倍多的差距,還是很明顯。


    評論

    # re: 一道面試題注記  回復(fù)  更多評論   

    2010-11-01 00:26 by yangwm
    你給出的算法, 源碼不全, 理解不了。

    我也寫了一個,可以看我的博客《最大N算法(前一版本的改進)》:
    MaxNAlgorithm比最簡單的排序后取最大的n位, 效率高十陪以上(當然需排序結(jié)果也要有足夠大才行; 測試結(jié)果只是個比較而已,因為vm沒有先預(yù)熱以及相應(yīng)參數(shù)配置)。

    # re: 一道面試題注記  回復(fù)  更多評論   

    2010-11-01 09:28 by denniis
    @yangwm
    這源碼很全了吧……

    # re: 一道面試題注記  回復(fù)  更多評論   

    2010-11-01 09:35 by dennis
    @yangwm
    不好意思,是遺漏來med3這個方法,補上。這個算法跟快排的分治算法是一樣的,快排可以用的那些優(yōu)化手段也可以在這里用上。

    # re: 一道面試題注記  回復(fù)  更多評論   

    2010-11-01 09:41 by dennis
    @yangwm
    我測試下我的實現(xiàn),大概比你的那個實現(xiàn)還快上4-5倍,不過你的實現(xiàn)多了一個box/unbox的開銷,本身就不公平。當然,我上面提到來,我的這個實現(xiàn)還有改進的空間:改進劃分算法,當子段小的時候不做遞歸而做排序等等。

    另外就是我的結(jié)果集合是沒有排序的,你的測試程序只輸出前10個,因此看起來結(jié)果不同,將結(jié)果全部排序并輸出即可驗證我的程序也是正確的。

    # re: 一道面試題注記  回復(fù)  更多評論   

    2010-11-01 22:13 by yangwm
    我的那個算法改為基本類型版的吧。
    同時與你的你的算法做了一下對比測試。
    實現(xiàn)比你的還快一些。

    # re: 一道面試題注記  回復(fù)  更多評論   

    2010-11-01 22:15 by yangwm
    http://blog.csdn.net/yang_net/archive/2010/11/01/5978488.aspx

    # re: 一道面試題注記[未登錄]  回復(fù)  更多評論   

    2010-11-01 23:24 by dennis
    @yangwm

    說快或者說慢,總有個前提,以你的代碼為例,取前10個,是你的會快一些,而取前10000個,卻是我的快很多。此外,優(yōu)秀的算法還需要考慮其他情況,比如數(shù)組的重復(fù)元素比較多,比如數(shù)組已經(jīng)排序等等。我改進了一下劃分算法,有興趣可以再測試看看。

    # re: 一道面試題注記  回復(fù)  更多評論   

    2010-11-01 23:42 by dennis
    @yangwm
    1000萬取前10萬個,你的實現(xiàn)性能下降很驚人,比較奇怪。而我的這個實現(xiàn)可以在任意維度下維持一個優(yōu)秀的性能,包括各種特殊情況:數(shù)組已經(jīng)排序、數(shù)組重復(fù)元素非常多等。
    主站蜘蛛池模板: 激情内射亚洲一区二区三区爱妻| A毛片毛片看免费| 成人片黄网站色大片免费观看cn| 成人黄18免费视频| 午夜亚洲AV日韩AV无码大全| 日本高清不卡中文字幕免费| 最近中文字幕mv免费高清视频7 | 图图资源网亚洲综合网站| 亚洲国产精品免费观看| 亚洲成人黄色网址| 91香蕉国产线在线观看免费 | 亚洲性无码AV中文字幕| 亚洲精品在线免费观看视频| 夜夜亚洲天天久久| 午夜免费福利片观看| 亚洲国产精品成人精品无码区 | 亚洲精品无码不卡在线播放| 国产精品成人免费视频网站京东| 亚洲伊人久久大香线蕉结合| 啦啦啦手机完整免费高清观看| 2020久久精品亚洲热综合一本| 不卡一卡二卡三亚洲| 亚洲阿v天堂在线2017免费| 国产亚洲色视频在线| 成人毛片免费视频| 无码AV片在线观看免费| 成年免费大片黄在线观看com| 亚洲综合在线另类色区奇米| 国产羞羞的视频在线观看免费| 亚洲国产香蕉碰碰人人| 成年女人免费视频播放体验区| 成人爽a毛片免费| 亚洲国产成人在线视频| 国内自产拍自a免费毛片| 久久久久久夜精品精品免费啦| 亚洲一区二区三区在线| 亚洲大尺度无码专区尤物| 亚洲VA综合VA国产产VA中| 中文字幕无线码中文字幕免费| 色偷偷尼玛图亚洲综合| 国产亚洲欧洲Aⅴ综合一区|