K‘ 未排序数组中的最小/最大元素 |期望线性时间

给定一个不同整数的数组和一个整数,其中 小于数组大小,任务是找到数组中第 k 个最小的元素。

示例:

请注意,解决这个问题的方法有多种,详见《未排序数组中的k个最小/最大元素》。这里讨论的解决方案在实践中效果最佳。

其理念是使用随机枢轴选择来划分数组,通过聚焦子数组(第k个元素必须所在)来减少搜索空间。

一步步的方法:

选择随机枢轴:随机选择一个元素作为枢轴。这有助于避免某些情况下的最坏情况(比如数组已经排序)。

划分:重新排列数组,使所有小于枢轴的元素位于左侧,大于枢轴的元素在右侧。

递归搜索:一旦枢轴定位,如果其索引等于 n 的比较,则它是第 K 大元素。如果没有,则递归搜索相应的划分(左或右),其中 n。

复制代码
// Java program to find K'th Smallest/
// Largest Element in Unsorted Array
import java.util.Random;

class GfG {  
    
    // Partition function: Rearranges elements 
    // around a pivot (last element)
    static int partition(int[] arr, int l, int r) {  
        int x = arr[r];  
        int i = l;     

        // Iterate through the subarray
        for (int j = l; j <= r - 1; j++) {  
            
            // Move elements <= pivot to the left partition
            if (arr[j] <= x) {  
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                i++; 
            }  
        }  
        
        // Place the pivot in its correct position
        int temp = arr[i];
        arr[i] = arr[r];
        arr[r] = temp;
        return i;  
    }  

    // Randomizes the pivot to avoid worst-case performance
    static int randomPartition(int[] arr, int l, int r) {  
        Random rand = new Random();
        int n = r - l + 1;  
        int pivot = rand.nextInt(n);      
        int temp = arr[l + pivot];
        arr[l + pivot] = arr[r];
        arr[r] = temp;
        return partition(arr, l, r); 
    }  

    // function to find the k'th smallest element using QuickSelect
    static int quickSelect(int[] arr, int l, int r, int k) {  
        
        // Check if k is within the valid range of 
        // the current subarray
        if (k > 0 && k <= r - l + 1) {  
            
            // Partition the array and get the
            // pivot's final position
            int pos = randomPartition(arr, l, r);  

            // If pivot is the k'th element, return it
            if (pos - l == k - 1)  
                return arr[pos];  

            // If pivot's position is larger than k,
            // search left subarray
            if (pos - l > k - 1)  
                return quickSelect(arr, l, pos - 1, k);  

            // Otherwise, search right subarray and adjust k 
            // (k is reduced by the size of the left partition)
            return quickSelect(arr, pos + 1, r, k - (pos - l + 1));  
        }  
        
        // Return infinity for invalid k (error handling)
        return Integer.MAX_VALUE;  
    }

    static int kthSmallest(int[] arr, int k) {
        int n = arr.length;
        return quickSelect(arr, 0, n - 1, k);
    }

    public static void main(String[] args) {  
        int[] arr = {12, 3, 5, 7, 4, 19, 26};  
        int k = 3;  
        System.out.println(kthSmallest(arr, k));  
    }  
}

输出

5

时间复杂度:O(n) 上述解的最坏情况下时间复杂度仍为 O(n2)。在最坏情况下,随机函数可能总是选择一个角元素。然而,平均情况下的时间复杂度为 。分析假设随机数生成器生成输入范围内任意数字的可能性相等。

辅助空间: 自使用常数变量以来,O(1)。O(n)

即使最坏时间复杂度是二次方,这种解在实际中也表现最佳。

复制代码
编程资源
https://pan.quark.cn/s/7f7c83756948
更多资源
https://pan.quark.cn/s/bda57957c548
相关推荐
逝水如流年轻往返染尘5 分钟前
JAVA中的抽象类
java·开发语言
旖-旎7 分钟前
二分查找(1)
c++·算法·二分查找·力扣·双指针
困死,根本不会11 分钟前
【C 语言】指针学习笔记:从底层原理到实战应用
c语言·开发语言·笔记·学习·算法
小范自学编程19 分钟前
算法训练营 Day38 - 动态规划part07
算法·动态规划
hx8622730 分钟前
Java MySQL 连接
java·mysql·adb
lpfasd12333 分钟前
Kubernetes (K8s) 底层早已不再直接使用 Docker 引擎了
java·docker·kubernetes
aq553560036 分钟前
SpringBoot有几种获取Request对象的方法
java·spring boot·后端
星空露珠1 小时前
迷你世界UGC3.0脚本Wiki全局函数
开发语言·数据库·算法·游戏·lua
小王不爱笑1321 小时前
排序算法 Java
数据结构·算法·排序算法
无敌憨憨大王1 小时前
二叉树的最短路径长度(BFS+DFS)
算法·深度优先·宽度优先