算法思想一:冒泡局部排序

解题思路:

只排序前K个数

1、主要利用冒泡排序算法对数组进行排序

2、从排序后的数组中直接获取第K大的数值

代码展示:

Python版本

class Solution:
    def findKth(self, a, n, K):
        # write code here
        # 冒泡排序  只需要对top K个数进行排序
        for i in range(K):
            for j in range(n-i-1):
                if a[j] > a[j+1]:
                    # 交换两个数字
                    tmp = a[j]
                    a[j] = a[j+1]
                    a[j+1] = tmp
        return a[n-K]

复杂度分析

时间复杂度:N表示数组长度,最差情况K趋近与n时复杂度为

空间复杂度:仅使用常数级空间变量

算法思想二:快排+二分

解题思路:

  • 采用快速排序,每次以当前表中第一个元素为轴来对表进行划分,将表中比枢轴大的元素向左移,比表中小的元素向右移,使得下一趟partition操作后,表中的元素备枢轴一份为二。每次partition可以确定一个第大元素,如果,则是第K大元素
  • 找到第K大的数,也就是找到数组排序后位于n-K位置的数,利用快排的partation函数,可以得到一个数的位置index。如果,则返回,如果小于index 则在做边区间去找,如果大于则在右半区间找。

代码展示:

JAVA版本

import java.util.*;
public class Solution {
    public int findKth(int[] a, int n, int K) {
        // write code here
        // 快速排序
        return quickSort(a, 0, a.length - 1, K);
    }
    private int quickSort(int[] arr, int left, int right, int k){
        int p = partition(arr, left, right);
        // 改进后,很特殊的是,p是全局下标,只要p对上topK坐标就可以返回
        if (p == arr.length - k) {
            return arr[p];
        }else if (p < arr.length - k) {
            // 如果基准在左边,这在右边找
            return quickSort(arr, p + 1, right,k);
        }else {
            return quickSort(arr, left, p - 1,k);
        }
    }

    private int partition(int[] arr, int left, int right) {
        // 可优化成随机,或中位数
        int key = arr[left];
        while (left < right) {
            while (left = key) right--;
            arr[left] = arr[right];
            while (left < right && arr[left] <= key) left++;
            arr[right] = arr[left];
        }
        arr[left] = key;
        return left;
    }
}

复杂度分析

时间复杂度:N表示数组长度,查找时间,随机选择时间

空间复杂度:递归调用栈空间

算法思想三:小根堆

解题思路:

通过构造小根堆进行数组排序,在排序过程中查找第K大的点
算法流程:

1、遍历数组

2、如果堆的大小小于K,则将数组元素入堆,反之,移除堆的根,并将当前元素入堆

3、遍历结束返回 堆的首元素

代码展示:

JAVA版本

import java.util.*;
public class Solution {
    public int findKth(int[] a, int n, int K) {
        // write code here
        //小根堆
        PriorityQueue pq = new PriorityQueue() ;
        for(int i = 0 ; i < n ; i++)
        {
            if(pq.size() < K)
            {
                pq.add(a[i]) ;
            }else if(a[i] > pq.peek()){
                pq.remove() ;
                pq.add(a[i]) ;
            }
        }
        return pq.peek();
    }
}

复杂度分析

时间复杂度:N表示数组长度,构建堆时间,操作堆时间

空间复杂度:堆空间