bobo老师,为啥三路快排的思想在程序员面试经典就要超时呢?代码如下

bobo老师,为啥三路快排的思想在程序员面试经典就要超时呢?代码如下

    public int[] getLeastNumbers(int[] arr, int k) {
        if (k == 0) {
            return new int[0];
        }
        return getLeastNumbers(arr, 0, arr.length - 1, k);
    }

    private int[] getLeastNumbers(int[] arr, int l, int r, int k) {
        int idx = new Random().nextInt(r - l + 1) + l;
        swap(arr, idx, l);
        // arr[l+1,lt]<arr[l] arr[lt+1,i-1]=arr[l] arr[gt,r]>arr[l]
        int lt = l, i = l + 1, gt = r + 1;
        while (i < gt) {
            if (arr[i] == arr[l]) {
                i++;
            } else if (arr[i] > arr[l]) {
                gt--;
                swap(arr, i, gt);
            } else {
                lt++;
                swap(arr, i, lt);
                i++;
            }
        }
        swap(arr, lt, l);
        if (lt == k - 1) {
            return Arrays.copyOf(arr, k);
        } else if (lt < k - 1) {
            return getLeastNumbers(arr, l + 1, r, k);
        } else {
            return getLeastNumbers(arr, l, r - 1, k);
        }
    }

    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
liuyubobobo 2022-02-02 12:55:02

请给我问题链接和完整可以提交的代码,谢谢。


==========


你的递归过程,每次只会将处理的区间 -1(l + 1 或者 r - 1),所以最差情况下,整个递归函数会执行 n 层。而整个递归函数的时间是 O(n) 的,所以算法整体是 O(n^2) 的。


请先仔细理解这里我提供的基于双路排序的 selectK 问题的代码。递归过程,每次能排除掉“一半”的元素:https://class.imooc.com/lesson/1582#mid=37054


以下代码是我根据你的代码修改的可以 ac 的代码,注意在递归过程中的变化(注释部分):


class Solution {

    public int[] smallestK(int[] arr, int k) {
        if (k == 0) {
            return new int[0];
        }
        getLeastNumbers(arr, 0, arr.length - 1, k);
        return Arrays.copyOf(arr, k);
    }

    private void getLeastNumbers(int[] arr, int l, int r, int k) {
        int idx = new Random().nextInt(r - l + 1) + l;
        swap(arr, idx, l);
    
        // arr[l+1,lt]<arr[l] arr[lt+1,i-1]=arr[l] arr[gt,r]>arr[l]
        int lt = l, i = l + 1, gt = r + 1;
        while (i < gt) {
            if (arr[i] == arr[l]) {
                i++;
            } else if (arr[i] > arr[l]) {
                gt--;
                swap(arr, i, gt);
            } else {
                lt++;   
                swap(arr, i, lt);
                i++;
            }
        }
        
        swap(arr, lt, l);
       
        // 每次递归可以或者排除掉 lt 端的所有元素,
        // 或者排除掉 gt 端的所有元素
        if(k - 1 <= lt - 1){
            getLeastNumbers(arr, l, lt - 1, k);
        }
        else if(k - 1 >= gt){
            getLeastNumbers(arr, gt, r, k);
        }
    }

    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}


继续加油!:)

  • 提问者 我要跳槽 #1
    问题连接:https://leetcode-cn.com/problems/smallest-k-lcci/
    class Solution {    
        public int[] smallestK(int[] arr, int k) {        
            if (k == 0) {            
                return new int[0];
            }        
            return getLeastNumbers(arr, 0, arr.length - 1, k);
        }    
        private int[] getLeastNumbers(int[] arr, int l, int r, int k) {        
            int idx = new Random().nextInt(r - l + 1) + l;
            swap(arr, idx, l);        
            // arr[l+1,lt]<arr[l] arr[lt+1,i-1]=arr[l] arr[gt,r]>arr[l]
            int lt = l, i = l + 1, gt = r + 1;        
            while (i < gt) {            
                if (arr[i] == arr[l]) {
                    i++;
                } else if (arr[i] > arr[l]) {
                    gt--;
                    swap(arr, i, gt);
                } else {
                    lt++;
                    swap(arr, i, lt);
                    i++;
                }
            }
            swap(arr, lt, l);        
            if (lt == k - 1) {            
                return Arrays.copyOf(arr, k);
            } else if (lt < k - 1) {            
                return getLeastNumbers(arr, l + 1, r, k);
            } else {            
                return getLeastNumbers(arr, l, r - 1, k);
            }
        }    
        private void swap(int[] arr, int i, int j) {        
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    
    }


    2022-02-02 15:40:34
  • liuyubobobo 回复 提问者 我要跳槽 #2

    我补充在了原回答中。继续加油!:)

    2022-02-02 17:36:55
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
算法与数据结构
  • 参与学习       2589    人
  • 解答问题       1090    个

慕课网算法名师Liuyubobobo,5年集大成之作 从0到工作5年,算法与数据结构系统解决方案

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师