zoukankan      html  css  js  c++  java
  • Easy | 剑指 Offer 40. 最小的k个数 | 快排

    剑指 Offer 40. 最小的k个数

    输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

    示例 1:

    输入:arr = [3,2,1], k = 2
    输出:[1,2] 或者 [2,1]
    

    示例 2:

    输入:arr = [0,1,2,1], k = 1
    输出:[0]
    

    限制:

    • 0 <= k <= arr.length <= 10000
    • 0 <= arr[i] <= 10000

    解题思路

    快速排序。

    public int[] getLeastNumbers(int[] arr, int k) {
        if (arr == null || arr.length == 0 || k == 0) {
            return new int[0];
        }      
        return quickSearch(arr, 0, arr.length-1, k);
    }
    
    private int[] quickSearch(int[] arr, int lower, int upper, int k) {
        int pos = partition(arr, lower, upper);
        if (pos == k -1) {
            return Arrays.copyOf(arr, k);
        }
        return pos > k - 1 ? quickSearch(arr, lower, pos-1, k) : quickSearch(arr, pos + 1, upper, k);
    }
    // 这是一个直接赋值的写法
    public int partition(int[] arr, int left, int right) {
        int pivot = arr[left];
        // 维持两个指针l和r, 在运动的过程中,保证l左边的元素都小于等于pivot, r右边的元素都大于pivot
        int l = left, r = right;
        while(l < r) {
            // 先把右边小于枢纽值的元素放到左边
            while(arr[r] >= pivot && l < r) r--;
            arr[l] = arr[r];
            // 再把左边大于枢纽值的元素放到右边
            while(arr[l] <= pivot && l < r) l++;
            arr[r] = arr[l];
        }
        arr[l] = pivot;
        return l;   
    }
    

    另外一种写法

    public int[] getLeastNumbers(int[] arr, int k) {
        randomizedSelected(arr, 0, arr.length - 1, k);
        return Arrays.copyOf(arr, k);
    }
    
    public void randomizedSelected(int[] arr, int l, int r, int k) {
        if (l >= r) {
            return;
        }
        int pos = randomizedPartition(arr, l, r);
        int num = pos - l + 1;
        if (k == num) {
            return;
        } else if (k < num) {
            randomizedSelected(arr, l, pos - 1, k);
        } else {
            randomizedSelected(arr, pos + 1, r, k - num);
        }
    }
    
    // 基于随机的划分
    public int randomizedPartition(int[] nums, int l, int r) {
        int i = new Random().nextInt(r - l + 1) + l;
        swap(nums, r, i);
        return partition(nums, l, r);
    }
    
    public int partition(int[] nums, int l, int r) {
        // 以最右边的元素做枢纽值
        int pivot = nums[r];
        int i = l - 1;
        // 从左往右扫描, 
        for (int j = l; j <= r - 1; ++j) {
            if (nums[j] <= pivot) {
                // 直到遇到一个小于枢纽值的元素, 把其交换到i的下一个位置
                i = i + 1;
                swap(nums, i, j);
            }
            // 如果遇到的值大于枢纽值, 则j指针向前走, 
            // i 指针仍然指向那个不超过枢纽值的最大元素
        }
        // 当数据遍历完成时, 所有小于枢纽值的元素全部都放到[l, i]区间了。
        // 那么只需要将枢纽值交换到 i + 1的位置, 就可以了。
        swap(nums, i + 1, r);
        return i + 1;
    }
    
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
    
  • 相关阅读:
    dig命令不能使用(-bash: dig: command not found)
    linux系统中的一些典型问题汇总
    Django运行项目时候出现DisallowedHost at / Invalid HTTP_HOST header:
    Grafana添加Zabbix为数据源(二)
    Grafana添加Zabbix为数据源(一)
    linux go环境安装
    centos6里面装zabbix(五)
    centos6里面装zabbix(二)
    HTTP状态码分类及异常状态码处理
    超详细 Linux 下编译安装Redis 以及php配套使用
  • 原文地址:https://www.cnblogs.com/chenrj97/p/14289199.html
Copyright © 2011-2022 走看看