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
相关推荐
tqs_123451 小时前
MySQL RR隔离级别死锁|Gap间隙锁、临键锁,订单并发范围查询死锁根因方案
java
逆境不可逃1 小时前
Pi Agent 学习笔记:多个工具怎样并行执行
java
v_34836087622 小时前
Android native端 堆栈打印
android·算法
residual_fan2 小时前
【学术论文】航空发动机故障诊断智能体:基于持续对比强化学习的动态优化方法
人工智能·算法·数据挖掘·数据分析
Flynt2 小时前
Java 27 升级实测:默认值动得比新特性多,有个老参数会让 JVM 直接起不来
java·jvm·后端
Bs_MoneyMagnet2 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
GreenTea2 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持2 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
niucloud-admin3 小时前
JAVA V6 多商户商城 开发文档——job 计划任务开发
java·python·github
深圳满意度咨询3 小时前
医院满意度数字化测评系统:从数据采集到智能决策的技术实践
算法