力扣215:数组中的第K个最大元素 (leetcode 215:Kth Largest Element In An Array)

2 篇文章 0 订阅
2 篇文章 0 订阅

题目链接:https://leetcode.cn/problems/kth-largest-element-in-an-array


一、题目描述

1.中文

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题.

        示例 1:

        输入: [3,2,1,5,6,4], k = 2
        输出: 5

        示例 2:

        输入: [3,2,3,1,2,4,5,5,6], k = 4
        输出: 4

2.英文   

Given an integer array nums and an integer k, return the kth largest element in the array.

Note that it is the kth largest element in the sorted order, not the kth distinct element.

You must solve it in O(n) time complexity.

二、解决方法

1.直接排序

代码如下:

public static int findKthLargest(int[] nums, int k) {
		//直接排序
		Arrays.sort(nums);
		return nums[nums.length - k];
}

时间复杂度:Arrays.sort()是经过调优的排序算法,时间复杂度可以达到O(n*log(n))。

2.基于快速排序的选择算法

代码如下:

package sort;

import java.util.Arrays;
import java.util.Collections;
import java.util.PriorityQueue;

public class KthLargestNum {

	public static void main(String[] args) {
		int[] nums = {3,2,3,1,2,4,5,5,6};
		int k = 4;
		int kthLargest = findKthLargest(nums, k);
		System.out.println(kthLargest);
	}


	public static int findKthLargest(int[] nums, int k) {
		return quickSort(nums,0,nums.length-1,k);
	}

	private static int quickSort(int[] nums, int l, int r, int k) {
		int index = randomPartition(nums,l,r);//基准值索引
		if (index == k - 1){
			return nums[index];
		}else {
			if (index > k - 1) {
				return quickSort(nums, l, index - 1, k);
			} else {
				return quickSort(nums, index + 1, r, k);
			}
		}
	}

	private static int randomPartition(int[] nums,int l,int r){
		int index = (int) (Math.random() * (r - l)) + l;//随机索引
		swap(nums,index,r);//把索引为index的值放在数组最后,对前面的数组进行排序
		return partition(nums,l,r);
	}

	public static void swap(int[] nums,int i ,int j){
		int temp = nums[i];
		nums[i] = nums[j];
		nums[j] = temp;
	}

	//将数组按照pivot分成左右两边,左边大右边小
	private static int partition(int[] nums,int l,int r){
		int pivot = nums[r];
		int right = r;//pivot的位置索引
		while (l <= r){
			while (l <= r && nums[l] > pivot){
				l++;
			}
			while (l <= r && nums[r] <= pivot){
				r--;
			}
			if (l <= r){
				swap(nums,l,r);
			}
		}
		//把pivot放在分配好的两侧之间
		swap(nums,l,right);
		return l;
	}

}

时间复杂度:O(n),证明过程可以参考「《算法导论》9.2:期望为线性的选择算法」。

3.堆排序

package sort;

import java.util.Arrays;
import java.util.Collections;
import java.util.PriorityQueue;

public class KthLargestNum_215 {

	public static void main(String[] args) {
		int[] nums = {3,2,3,1,2,4,5,5,6};
		int k = 4;
		int kthLargest = findKthLargest(nums, k);
		System.out.println(kthLargest);
	}


	public static int findKthLargest(int[] nums, int k) {

		//小顶堆
		PriorityQueue<Integer> minHeap = new PriorityQueue<>();
		//堆里只留最大的两个值
		for (int num : nums){
			minHeap.add(num);
			if (minHeap.size() > k){
				minHeap.poll();
			}
		}
		return minHeap.peek();


		//大顶堆
		PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
		for (int num : nums){
			maxHeap.add(num);
		}
		for (int i = 1; i <= k - 1; i++) {
			maxHeap.poll();
		}
		return maxHeap.peek();
	}
}

      时间复杂度:O(nlog⁡n),建堆的时间代价是 O(n),删除的总代价是 O(klog⁡n),因为 k<n,故渐进时间复杂为 O(n+klog⁡n)=O(nlog⁡n)。


总结

        综上所述,题目要求复杂度为O(n),所有采用基于快速排序的选择算法最佳。

       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值