📌  相关文章
📜  未排序数组中第K个最小/最大元素|设置2(预期线性时间)

📅  最后修改于: 2021-04-29 09:41:39             🧑  作者: Mango

我们建议阅读以下文章,作为该文章的先决条件。

未排序数组中第K个最小/最大元素|套装1

给定一个数组和一个数k(其中k小于数组的大小),我们需要在给定数组中找到第k个最大的元素。假定所有数组元素都是不同的。

例子:

Input: arr[] = {7, 10, 4, 3, 20, 15}
       k = 3
Output: 7

Input: arr[] = {7, 10, 4, 3, 20, 15}
       k = 4
Output: 10

我们在这里讨论了三种不同的解决方案。

在这篇文章中,讨论了方法4,它主要是对上一篇文章中讨论的方法3(QuickSelect)的扩展。

C++
// C++ implementation of above implementation
#include
#include
#include
using namespace std;
  
int randomPartition(int arr[], int l, int r);
  
// This function returns k'th smallest element in arr[l..r] using
// QuickSort based method.  ASSUMPTION: ALL ELEMENTS IN ARR[] ARE DISTINCT
int kthSmallest(int arr[], int l, int r, int k)
{
    // If k is smaller than number of elements in array
    if (k > 0 && k <= r - l + 1)
    {
        // Partition the array around last element and get
        // position of pivot element in sorted array
        int pos = randomPartition(arr, l, r);
  
        // If position is same as k
        if (pos-l == k-1)
            return arr[pos];
        if (pos-l > k-1)  // If position is more, recur for left subarray
            return kthSmallest(arr, l, pos-1, k);
  
        // Else recur for right subarray
        return kthSmallest(arr, pos+1, r, k-pos+l-1);
    }
  
    // If k is more than number of elements in array
    return INT_MAX;
}
  
void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
  
// Standard partition process of QuickSort().  It considers the last
// element as pivot and moves all smaller element to left of it
// and greater elements to right
int partition(int arr[], int l, int r)
{
    int x = arr[r], i = l;
    for (int j = l; j <= r - 1; j++)
    {
        if (arr[j] <= x)
        {
            swap(&arr[i], &arr[j]);
            i++;
        }
    }
    swap(&arr[i], &arr[r]);
    return i;
}
  
int randomPartition(int arr[], int l, int r)
{
    int n = r-l+1;
    int pivot = rand() % n;
    swap(&arr[l + pivot], &arr[r]);
    return partition(arr, l, r);
}
  
// Driver program to test above methods
int main()
{
    int arr[] = {12, 3, 5, 7, 4, 19, 26};
    int n = sizeof(arr)/sizeof(arr[0]), k = 3;
    cout << "K'th smallest element is " << kthSmallest(arr, 0, n-1, k);
    return 0;
}


Java
// Java program of above implementation
import java.util.Random;
  
public class GFG {
  
// This function returns k'th smallest element in arr[l..r] using
// QuickSort based method. ASSUMPTION: ALL ELEMENTS IN ARR[] ARE DISTINCT
    static int kthSmallest(int arr[], int l, int r, int k) {
        // If k is smaller than number of elements in array
        if (k > 0 && k <= r - l + 1) {
            // Partition the array around last element and get
            // position of pivot element in sorted array
            int pos = randomPartition(arr, l, r);
  
            // If position is same as k
            if (pos - l == k - 1) {
                return arr[pos];
            }
            if (pos - l > k - 1) // If position is more, recur for left subarray
            {
                return kthSmallest(arr, l, pos - 1, k);
            }
  
            // Else recur for right subarray
            return kthSmallest(arr, pos + 1, r, k - pos + l - 1);
        }
  
        // If k is more than number of elements in array
        return Integer.MAX_VALUE;
    }
  
    static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
  
// Standard partition process of QuickSort(). It considers the last
// element as pivot and moves all smaller element to left of it
// and greater elements to right
    static int partition(int arr[], int l, int r) {
        int x = arr[r], i = l;
        for (int j = l; j <= r - 1; j++) {
            if (arr[j] <= x) {
                swap(arr, i, j);
                i++;
            }
        }
        swap(arr, i, r);
        return i;
    }
  
    static int randomPartition(int arr[], int l, int r) {
        int n = r - l + 1;
        int pivot = new Random().nextInt(1);
        swap(arr, l + pivot, r);
        return partition(arr, l, r);
    }
  
// Driver program to test above methods
    public static void main(String args[]) {
        int arr[] = {12, 3, 5, 7, 4, 19, 26};
        int n = arr.length, k = 3;
        System.out.println("K'th smallest element is " + kthSmallest(arr, 0, n - 1, k));
    }
}
  
/*This code is contributed by 29AjayKumar*/


Python3
# Python3 implementation of above implementation
  
# This function returns k'th smallest element 
# in arr[l..r] using QuickSort based method.
# ASSUMPTION: ALL ELEMENTS IN ARR[] ARE DISTINCT
from random import randint
  
def randomPartition(arr, l, r):
    n = r - l + 1
    pivot = randint(1, 100) % n
    arr[l + pivot], arr[r] = arr[l + pivot], arr[r]
    return partition(arr, l, r)
  
def kthSmallest(arr, l, r, k):
  
    # If k is smaller than 
    # number of elements in array
    if (k > 0 and k <= r - l + 1):
  
        # Partition the array around last element and 
        # get position of pivot element in sorted array
        pos = randomPartition(arr, l, r)
  
        # If position is same as k
        if (pos - l == k - 1):
            return arr[pos]
              
        # If position is more, recur for left subarray
        if (pos - l > k - 1): 
            return kthSmallest(arr, l, pos - 1, k)
  
        # Else recur for right subarray
        return kthSmallest(arr, pos + 1, r,
                           k - pos + l - 1)
  
    # If k is more than number of elements in array
    return 10**9
  
# Standard partition process of QuickSort(). 
# It considers the last element as pivot and 
# moves all smaller element to left of it
# and greater elements to right
def partition(arr, l, r):
    x = arr[r]
    i = l
    for j in range(l, r):
        if (arr[j] <= x):
            arr[i], arr[j] = arr[j], arr[i]
            i += 1
  
    arr[i], arr[r] = arr[r], arr[i]
    return i
  
# Driver Code
arr = [12, 3, 5, 7, 4, 19, 26]
n = len(arr)
k = 3
print("K'th smallest element is", 
       kthSmallest(arr, 0, n - 1, k))
  
# This code is contributed by Mohit Kumar


C#
// C# program of above implementation
using System;
  
class GFG 
{ 
  
// This function returns k'th smallest 
// element in arr[l..r] using 
// QuickSort based method. ASSUMPTION: 
// ALL ELEMENTS IN ARR[] ARE DISTINCT 
static int kthSmallest(int []arr, int l,
                       int r, int k) 
{ 
    // If k is smaller than number 
    // of elements in array 
    if (k > 0 && k <= r - l + 1) 
    {
        // Partition the array around last 
        // element and get position of pivot
        // element in sorted array 
        int pos = randomPartition(arr, l, r); 
  
        // If position is same as k 
        if (pos - l == k - 1) 
        { 
            return arr[pos]; 
        } 
          
        // If position is more, recur 
        // for left subarray 
        if (pos - l > k - 1) 
        { 
            return kthSmallest(arr, l, pos - 1, k); 
        } 
  
        // Else recur for right subarray 
        return kthSmallest(arr, pos + 1, r,
                           k - pos + l - 1); 
    } 
  
    // If k is more than number of 
    // elements in array 
    return int.MaxValue; 
} 
  
static void swap(int[] arr, int i, int j)
{ 
    int temp = arr[i]; 
    arr[i] = arr[j]; 
    arr[j] = temp; 
} 
  
// Standard partition process of QuickSort(). 
// It considers the last element as pivot and 
// oves all smaller element to left of it 
// and greater elements to right 
static int partition(int []arr, int l, int r) 
{ 
    int x = arr[r], i = l; 
    for (int j = l; j <= r - 1; j++)
    { 
        if (arr[j] <= x) 
        { 
            swap(arr, i, j); 
            i++; 
        } 
    } 
    swap(arr, i, r); 
    return i; 
} 
  
static int randomPartition(int []arr, int l, int r)
{ 
    int n = r - l + 1; 
    int pivot = new Random().Next(1); 
    swap(arr, l + pivot, r); 
    return partition(arr, l, r); 
} 
  
// Driver Code
public static void Main()
{ 
    int []arr = {12, 3, 5, 7, 4, 19, 26}; 
    int n = arr.Length, k = 3; 
    Console.WriteLine("K'th smallest element is " + 
                    kthSmallest(arr, 0, n - 1, k)); 
} 
} 
  
// his code is contributed by 29AjayKumar


输出:

K'th smallest element is 5


参考:

https://www.geeksforgeeks.org/kth-smallestlargest-element-unsorted-array/