Java不排序求第k小元素

题目描述:

输入一个整数数组,请求出该数组的第k小元素。要求时间复杂度为O(n)。

输入:

每组输入包括两行,第一行为一个整数数组,两个数字之间用空格隔开;第二行为k值。数组中元素个数小于10^9。

输出:

输出第k小元素的值。

解题思路:

通过快速排序中的分割方法求解。你可以通过分割是的某个数的前面的数大于等于它,后面的数小于它,或者某个数的前面的数小于等于它,后面的数大于它。由此可确定一个数在某有序序列中的正确位置。这里是求第k小元素,所以是升序。我们通过分割求出第k小元素的范围或者值。

代码:

import java.util.Random;
import java.util.Scanner;

public class DemoSix {
    
    
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
    
    
            String str = sc.nextLine();
            String str2 = sc.nextLine();
            int num = Integer.parseInt(str2);
            String[] arrString = str.split(" ");
            int[] arrNum = new int[arrString.length];
            for (int i = 0; i < arrString.length; i++) {
    
    
                arrNum[i] = Integer.parseInt(arrString[i]);
            }
            arrString = null;
            int result = quickSelect(arrNum, 0, arrNum.length - 1, num - 1);
            if (result != -1) {
    
    
                System.out.println(arrNum[result]);
            }
        }
        sc.close();

    }
    
    public static int quickSelect(int[] arr, int start, int end, int key) {
    
    
        if (start > end)
            return -1;
    
        int pivotPosition = partition(arr, start, end);
        if (key == pivotPosition) {
    
    
            return pivotPosition;
        } else if (key < pivotPosition) {
    
    
            return quickSelect(arr, start, pivotPosition - 1, key);
        } else {
    
    
            return quickSelect(arr, pivotPosition + 1, end, key);
        }
    }
    
    public static int partition(int[] arr, int start, int end) {
    
    
        if (start == end)
            return start;
    
        int pivotPosition = getRandom(start, end);
      
        swap(arr, pivotPosition, start);
        pivotPosition = start;
    
        int pointerA = start;
        int pointerB;
        for (pointerB = pivotPosition + 1; pointerB <= end; pointerB++) {
    
    
            if (arr[pointerB] < arr[pivotPosition]) {
    
    
                pointerA++;
                swap(arr, pointerA, pointerB);
            }
        }
        swap(arr, pointerA, pivotPosition);
        pivotPosition = pointerA;
    
        return pivotPosition;
    }
    
    public static int getRandom(int start, int end) {
    
    
        Random random = new Random();
        int temp = random.nextInt(end - start + 1) + start;
        return temp;
    }
    
    public static void swap(int[] arr, int a, int b) {
    
    
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
    
    public static void printArray(int[] arr) {
    
    
        for(int i = 0; i < arr.length; i++) {
    
    
            System.out.print(arr[i]);
            if(i < arr.length -1) {
    
    
                System.out.print(" ");
            }
        }
        System.out.println();
    }

}

代码讲解:

quickSelect():对数据进行分割,确定第k小元素的范围或值。

partition(arr, start, end):分割方法的实现。对数组的第start个元素到第end个元素进行分割,使得某个数前面的数小于等于它,它后面的大于等于它。然后返回这个数的索引。这个数可以随便取,本代码中是根据start、end产生一个随机数随机取的

Guess you like

Origin blog.csdn.net/weixin_43394832/article/details/105317385