leetcode解题之215. Kth Largest Element in an Array java 版(第k大的数字)

在未排序的数组中找到第k个最大的元素。使用快速选择算法实现O(n)的时间复杂度,也可以利用最小堆在O(nlogk)时间内解决问题,并探讨其在寻找中位数上的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

215. Kth Largest Element in an Array

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.

查找数组第k大的数字

从一个未经排序的数组中找出第k大的元素。注意是排序之后的第k大,而非第k个不重复的元素可以假设k一定是有效的, 1 ≤ k ≤ 数组长度。O(n)解法:快速选择(QuickSelect)

public class Solution {
		public int findKthLargest(int[] nums, int k) {
			if (k < 1 || nums == null || nums.length < k) {
				throw new IllegalArgumentException();
			}
			return findKthLargest(nums, 0, nums.length - 1, k);
		}

		public int findKthLargest(int[] nums, int start, int end, int k) {

			// 中枢值
			int pivot = nums[start];
			int lo = start;
			int hi = end;

			while (lo < hi) {
				// 将小于中枢值的数移动到数组左边
				while (lo < hi && nums[hi] >= pivot) {
					hi--;
				}
				nums[lo] = nums[hi];

				// 将大于中枢值的数移动到数组右边
				while (lo < hi && nums[lo] <= pivot) {
					lo++;
				}
				nums[hi] = nums[lo];
			}

			nums[lo] = pivot;

			// 如果已经找到了
			if (end - lo + 1 == k) {
				return pivot;
			}
			// 第k大的数在lo位置的右边
			else if (end - lo + 1 > k) {
				return findKthLargest(nums, lo + 1, end, k);
			}
			// 第k大的数在lo位置的左边
			else {
				// k-(end-lo+1)
				// (end-lo+1):表示从lo位置开始到end位置的元素个数,就是舍掉右半部分
				// 原来的第k大变成k-(end-lo+1)大
				return findKthLargest(nums, start, lo - 1, k - (end - lo + 1));
			}
		}

使用最小堆

我们可以使用最小堆解决这个问题,有k个元素,当size大于k 的时候,删除,复杂度是O(nlog(k)).空间复杂度是O(k),

public int findKthLargest(int[] nums, int k) {
    PriorityQueue<Integer> q = new PriorityQueue<Integer>(k);
    for(int i: nums){
        q.offer(i);
 
        if(q.size()>k){
            q.poll();
        }
    }
 
    return q.peek();
}

同样的思想查找中位数;

中位数:

快速排序

partition

// 查找第k大的数字
	public static int findKthLargest(int[] nums, int k) {
		int len = nums.length;
		int lo = 0;
		int hi = len - 1;
		int index = partition(nums, len, lo, hi);
		while (index != len - k) {
			if (index > len - k) {
				hi = index - 1;
				index = partition(nums, len, lo, hi);
			} else {
				lo = index + 1;
				index = partition(nums, len, lo, hi);
			}
		}
		return nums[lo];
	}

	// 查找中位数,无序,有重复
	public static double findMidle(int[] nums) {
		int len = nums.length;
		int lo = 0;
		int hi = len - 1;
		int mid = len / 2;
		int index = partition(nums, len, lo, hi);
		while (index != mid) {
			if (index > mid) {
				hi = index - 1;
				index = partition(nums, len, lo, hi);
			} else {
				lo = index + 1;
				index = partition(nums, len, lo, hi);
			}
		}
		System.out.println(Arrays.toString(nums));
		System.out.println(mid);
		if (len % 2 == 1)
			return nums[lo];
		else
			return (nums[lo] + nums[lo - 1]) / 2.0;
	}

	// 快速排序
	public static void quickSort(int[] nums, int lo, int hi) {
		if (lo < hi) {
			int pivotPos = partition(nums, nums.length, lo, hi);
			quickSort(nums, lo, pivotPos - 1);
			quickSort(nums, pivotPos + 1, hi);
		}
	}

	// 基于快排的partition
	public static int partition(int[] nums, int len, int lo, int hi) {
		// 中枢值
		int pivot = nums[lo];
		while (lo < hi) {
			// 将小于中枢值的数移动到数组左边
			while (lo < hi && nums[hi] >= pivot)
				hi--;
			nums[lo] = nums[hi];
			// 将大于中枢值的数移动到数组右边
			while (lo < hi && nums[lo] <= pivot)
				lo++;
			nums[hi] = nums[lo];
		}
		// 枢轴元素存放的位置
		nums[lo] = pivot;
		// 返回枢轴的最终位置
		return lo;
	}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值