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.

Example 1:

Input: [3,2,1,5,6,4] and k = 2
Output: 5

Example 2:

Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4

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

翻译

在一个未排序的数组中找到第k大的元素. 注意是排好序的第k大元素, 不是第k个不同的元素.

例 1:

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

例 2:

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

注意:
你可以假设k始终有效, 1 ≤ k ≤ 数组长度.

程序

快速选择 不清晰思路

class Solution {
public:
    void swap(int& a,int& b)
    {
        int c = a;
        a = b;
        b = c;
    }
    void quickSort(vector<int>& nums,int left,int right)
    {
        //递归重要的返回条件
        if (left > right||right<=0||left>=nums.size()-1)return;
        int start = left;
        int end = right;
        int pivot = nums[right];
        while (left != right)
        {
            if (nums[left] > pivot)
            {
                if (nums[right] < pivot)
                    swap(nums[left], nums[right]);
                else
                    --right;
            }
            else
                ++left;

        }
        swap(nums[right],nums[end]);

        //要习惯递归的思维
        //这里不能直接写成从零开始,因为每次递归都不一样
        quickSort(nums, start, right-1);
        //这里不能直接写成从末尾开始,因为每次递归都不一样
        quickSort(nums, left+1, end);
    }
    int findKthLargest(vector<int>& nums, int k) {
        
        quickSort(nums,0,nums.size()-1);
        
        return nums[nums.size()-k];
        
    }
};

使用堆的思路

C++最小堆思路

int findKthLargest(vector<int>& nums, int k) {
	// 最小堆
	priority_queue< int, vector<int>, greater<int> > pq;

	// add first k elements to heap, since min heap, min element will be at top
	for (int i = 0; i < k; ++i) {
		pq.push(nums[i]);
	}

	// for rest of elements...
	// ... if it is greater than heap's top...
	// ... pop from heap and push num to heap
	// thereby maintaining heap size to be (k)

	// one by one, all numbers in heap become the (k) largest numbers in array

	for (int i = k; i < nums.size(); ++i) {
		if (nums[i] > pq.top()) {
			pq.pop();
			pq.push(nums[i]);
		}
	}

	// at the end, the number at top will be less than all numbers in heap
	// that is, it will be kth largest

	return pq.top();
}

代码出处

C 最大堆思路


//传入  数组与数组长度与当前节点与左节点与右节点
//返回   在当前节点与其子节点中返回最大的一个节点下标
int max(int *a, int n, int i, int j, int k) {
	int m = i;
	//j<n 是判断子节点是否存在
	if (j < n && a[j] > a[m]) {
		m = j;
	}
	if (k < n && a[k] > a[m]) {
		m = k;
	}
	return m;
}

//删除根节点
//传入  数组与数组长度与当前节点下标
void downheap(int *a, int n, int i) {
	while (1) {
		//从零开始不太好理解
		//2*i+1是左节点
		//2*i+2是右节点
		int j = max(a, n, i, 2 * i + 1, 2 * i + 2);
		//如果当前节点最大就没有  替换的必要了
		if (j == i) {
			break;
		}
		//将最大的子节点与当前节点进行替换
		int t = a[i];
		a[i] = a[j];
		a[j] = t;
		//将替换后的节点下标赋给i以便下次循环
		i = j;
	}
}

//堆排序
//传入  数组与数组长度
void heapsort(int *a, int n) {
	int i;
	//i从最后一个节点的父节点开始
	//因为数组从零开始所以-2
	//这一个for循环只是处理完全二叉树变成大顶堆
	for (i = (n - 2) / 2; i >= 0; i--)
	{
		//删除根节点    
		downheap(a, n, i);
	}
	for (int i = 0; i < n; i++)
	{
		cout << a[i] ;
	}
	cout << endl;
	//将最大值归位  即放在数组最后
	for (i = 0; i < n; i++)
	{
		int t = a[n - i - 1];
		a[n - i - 1] = a[0];
		a[0] = t;
		for (int i = 0; i < n; i++)
		{
			cout << a[i];
		}
		cout << endl;
		//每次数组长度都减i   代表数组后面已经排好了
		downheap(a, n - i - 1, 0);
	}
	for (int i = 0; i < n; i++)
	{
		cout << a[i] ;
	}
	cout << endl;
}

//小顶堆
int findKthLargest(int* nums, int numsSize, int k) {
	//如果数组为空   k大于数组长度    返回
	if (numsSize == 0) return 0;
	if (numsSize == 1) return nums[0];
	//进行堆排序
	heapsort(nums, numsSize);
	//取第k大的数
	return nums[numsSize - k];
}

代码出处
在这里插入图片描述

总结

  1. swap是c++标准库函数

  2. 什么是down-heap?
    对于最大堆,删除根节点就是删除最大值;
    对于最小堆,是删除最小值。
    然后,把堆存储的最后那个节点移到填在根节点处。
    再从上而下调整父节点与它的子节点:
    对于最大堆,父节点如果小于具有最大值的子节点,则交换二者。
    这一操作称作down-heap或bubble-down, percolate-down, sift-down, trickle down, heapify-down, cascade-down,extract-min/max等。

  3. 快速选择与快速排序的异同
    通过快速选择可以得到一组无序数字的第k大,原理基于快速排序,每次以某个数字为中点分成的左右两部分(程序中为了方便通常取最后一位,为了提高效率也可同时考虑开头中间结尾),左边都小于等于分割数,而右边都大于等于分割数

  4. 快速选择的平均时间复杂度是O(n),快速排序的平均时间复杂度是O(nlog(n))

  5. 快速排序(Quicksort),又称划分交换排序(partition-exchange sort)

参考

  1. Wiki二叉堆
  2. C的快排快选
  3. C++所有解题方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值