# 复习——Top K问题

class Solution {
public:

vector<int> getLeastNumbers(vector<int>& arr, int k) {
int n = arr.size();
if (n == k) return arr;
if (n < k || k <= 0 || n == 0) return{};
int low = 0, high = n - 1;
int pivotkey = partition(arr, low, high);
while (pivotkey != k)
{
if (pivotkey > k)
high = pivotkey - 1;
else
low = pivotkey + 1;
pivotkey = partition(arr, low, high);
}
return vector<int>(arr.begin(), arr.begin() + k);
}

int partition(vector<int>&a, int low, int high)//选第一个元素为枢轴
{
while (low < high)
{
while (low < high && a[high] >= a[low]) high--;//此时枢轴的下标为low
swap(a[low], a[high]); //交换后枢轴的下标为high

while (low < high && a[low] <= a[high]) low++; //此时枢轴的下标为high
swap(a[low], a[high]);//交换后枢轴的下标为low
}
return low;//返回枢轴的下标

}

};



//这里需要注意的是我们对完全二叉树结点的编号从0开始，所以如果父结点的编号为n，那么它的左孩子结点编号为2n+1，右孩子结点编号为2n+2
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
if (k == 0) return vector<int>();
vector<int> my_max_heap(arr.begin(), arr.begin() + k);//创建一个含有k个元素的大顶堆
buildMaxHeap(my_max_heap);

//start
for (int i = k; i < arr.size(); ++i)
{
// 出现比堆顶元素小的值, 置换堆顶元素, 并调整堆
if (arr[i] < my_max_heap[0])
{
replacePeek(my_max_heap, arr[i]);
}
}

return my_max_heap;
}
private:
void buildMaxHeap(vector<int>& v)
{
//从下往上，从右往左，将每个非叶子结点作为根结点，将其和其子树调整成大顶堆
for (int i = (v.size() - 2) / 2; i >= 0; --i) {
}
}

void HeapAdjust(vector<int>& v, int root_index) {
int temp = v[root_index];
int cur_root_index = root_index;

// 先初始化为左孩子结点索引
int child_index = 2 * cur_root_index + 1;
while (child_index < v.size()) {
// 判断是否存在右孩子, 并选出较大的结点，存入child_index
if (child_index + 1 < v.size() && v[child_index + 1] > v[child_index]) {
child_index += 1;
}
// 判断父结点和子结点的大小关系
if (temp >= v[child_index])
break;
// 较大结点上浮
v[cur_root_index] = v[child_index];
//为下一次循环做准备
cur_root_index = child_index;
child_index = 2 * cur_root_index + 1;
}
// cur_root_index就是根结点最终下沉到的位置的索引
v[cur_root_index] = temp;
}

void replacePeek(vector<int>& v, int val)
{
v[0] = val;
}
};


#include<iostream>
using namespace std;
void HeapSort(int* a, int num);
void HeapAdjust(int* a, int i, int num);
void swap(int* a, int i, int j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
#define Num 9
int main() {
int a[Num + 1] = { 0,50,10,90,30,70,40,80,60,20 };
int num = Num;
HeapSort(a, num);

for (int i = 1; i <= num; i++)
cout << a[i] << endl;

system("pause");
return 0;
}
void HeapSort(int* a, int num) {
for (int i = num / 2; i > 0; i--)//第一个循环：将数组a初始化为一个大顶堆

for (int i = num; i > 1; i--)//第二个循环：将大顶堆的根结点元素与大顶堆的最后一个结点元素交换，并且再重新调整新的大顶堆（此时注意新的大顶堆的总结点个数要减1）
{
swap(a, 1, i);
}
}

void HeapAdjust(int* a, int root_index, int num) {
int temp = a[root_index];
int cur_root_index = root_index;

// 先初始化为左孩子结点索引
int child_index = 2 * cur_root_index;
while (child_index <= num) {
// 判断是否存在右孩子, 并选出较大的结点，存入child_index
if (child_index + 1 <= num && a[child_index + 1] > a[child_index]) {
child_index += 1;
}
// 判断父结点和子结点的大小关系
if (temp >= a[child_index])
break;
// 较大结点上浮
a[cur_root_index] = a[child_index];
//为下一次循环做准备
cur_root_index = child_index;
child_index = 2 * cur_root_index;
}
// cur_root_index就是根结点最终下沉到的位置的索引
a[cur_root_index] = temp;

}


03-21 4803

05-29 2224

04-13 113

05-20 55

12-28 11

01-10 3989

05-11 27

09-08 1386

11-08 515

12-22 407

12-12 20

03-26 1万+

11-03 164

04-24 540

04-20 52

#### PHP 十万数字不同数组取最大的5个 (经典面试题topK) (原)

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客