描述
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
1 2
| 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5
|
示例 2:
1 2 3
| 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4
|
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
解题思路
首先,简单粗暴的思路就是将数组从大到小排序,然后直接取第k-1个数据,实现代码如下:
1 2 3 4 5 6 7 8 9 10
| int comp(const void*a, const void*b) { return *(int*)b - *(int*)a; }
int findKthLargest(int* nums, int numsSize, int k){ qsort(nums, numsSize, sizeof(int), comp); return nums[k-1]; }
|
当然,这道题本身是要考察对优先队列/堆这一数据结构的掌握情况。如果采用最大堆/最小堆的思路如下:
- 使用数组内容构建一个最大堆/最小堆
- 通过每次pop出堆顶元素来维护维护堆的结构
- 在满足一定的pop次数(最大堆K-1次,最小堆numSize-K次)以后,堆顶的元素就是第k大的数字
下面的代码是基于最大堆实现的代码,其中,最大堆数据结构代码参考慕课浙江大学《数据结构》公开课,地址如下:
浙江大学《数据结构》公开课
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
| typedef struct HNode *Heap; struct HNode { int *Data; int Size; int Capacity; }; typedef Heap MaxHeap; typedef Heap MinHeap; #define MAXDATA 100000 MaxHeap CreateHeap( int MaxSize ) { MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode)); H->Data = (int *)malloc((MaxSize+1)*sizeof(int)); H->Size = 0; H->Capacity = MaxSize; H->Data[0] = MAXDATA; return H; } bool IsFull( MaxHeap H ) { return (H->Size == H->Capacity); } bool Insert( MaxHeap H, int X ) { int i; if ( IsFull(H) ) { printf("最大堆已满"); return false; } i = ++H->Size; for ( ; H->Data[i/2] < X; i/=2 ) H->Data[i] = H->Data[i/2]; H->Data[i] = X; return true; } #define ERROR -1 bool IsEmpty( MaxHeap H ) { return (H->Size == 0); } int DeleteMax( MaxHeap H ) { int Parent, Child; int MaxItem, X; if ( IsEmpty(H) ) { printf("最大堆已为空"); return ERROR; } MaxItem = H->Data[1]; X = H->Data[H->Size--]; for( Parent=1; Parent*2<=H->Size; Parent=Child ) { Child = Parent * 2; if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) ) Child++; if( X >= H->Data[Child] ) break; else H->Data[Parent] = H->Data[Child]; } H->Data[Parent] = X; return MaxItem; }
void PercDown( MaxHeap H, int p ) { int Parent, Child; int X; X = H->Data[p]; for( Parent=p; Parent*2<=H->Size; Parent=Child ) { Child = Parent * 2; if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) ) Child++; if( X >= H->Data[Child] ) break; else H->Data[Parent] = H->Data[Child]; } H->Data[Parent] = X; } void BuildHeap( MaxHeap H ) { int i; for( i = H->Size/2; i>0; i-- ) PercDown( H, i ); }
int findKthLargest(int* nums, int numsSize, int k){ MaxHeap h = CreateHeap(numsSize); for(int i=0; i < numsSize; i++) Insert(h, nums[i]); BuildHeap(h); int result; for(int i=0; i<k; i++) { result = DeleteMax(h); } return result; }
|