一、冒泡排序
时间复杂度:O(n²)1520ms
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int length=nums.size();
for (int i = 0; i < length; i++) {
for (int j = i + 1; j < length; j++) {
if (nums[i] > nums[j]) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
//倒数第k个元素
return nums[length-k];
}
};
二、最大堆排序
Time:O(n)16ms
建堆的时间:O(n),排序堆的时间:O(n)
class Solution {
public:
//排序堆
void heap_Sort(vector<int>& sort, int n, int i) {
for (int j = n-1; j >=0; --j) {
swap(sort[j], sort[i]);
//顺序乱了,再次堆化
heapify(sort, j, 0);
}
}
//堆化 对象容器 容量 首元素
void heapify(vector<int>& ify, int n, int i) {
if (n <= i) {
return;
}
int c1 = i * 2 + 1;
int c2 = i * 2 + 2;
int max = i;
if (c1<n && ify[c1] > ify[max]) {
max = c1;
}
if (c2<n && ify[c2] > ify[max]) {
max = c2;
}
if (max != i) {
swap(ify[i],ify[max]);
heapify(ify, n, max);
}
}
//创建堆
void build_heap(vector<int>& bui, int n) {
//找到末节点的父节点
int i = n - 1;
int parent = (i - 1) / 2;
//堆化,使得该父节点一下的节点都符合规范,并依次堆化该父节点的上一节点
for (int i = parent; parent >= 0; --parent) {
heapify(bui, n, parent);
}
}
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size();
build_heap(nums, n);
heap_Sort(nums, n, 0);
return nums[n - k];
}
};
二点五、最大堆优化
Time:O(n log n)8ms
建堆:O(n),根据k删除堆:O(klog n)
class Solution {
public:
//排序堆{对代码不起作用但能使运行时间减少4ms}{迷惑}
void heap_Sort(vector<int>& sort, int n, int i) {
for (int j = n-1; j >=0; --j) {
swap(sort[j], sort[i]);
//顺序乱了,再堆化一次
heapify(sort, j, 0);
}
}
//堆化 对象容器 容量 要开始堆化的元素
void heapify(vector<int>& ify, int n, int i) {
if (n <= i) {
return;
}
int c1 = i * 2 + 1;
int c2 = i * 2 + 2;
int max = i;
if (c1<n && ify[c1] > ify[max]) {
max = c1;
}
if (c2<n && ify[c2] > ify[max]) {
max = c2;
}
if (max != i) {
swap(ify[i],ify[max]);
heapify(ify, n, max);
}
}
//创建大根堆
void build_heap(vector<int>& bui, int n) {
//找到末节点的父节点
int last_Node = n - 1;
//parent=n/2
int parent = (last_Node - 1)/2;//log n
//堆化,使得该父节点一下的节点都符合规范,并依次堆化该父节点的上一节点
for (int i = parent; i >= 0; --i) {
heapify(bui, n, i);
}
}
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size();//9
build_heap(nums, n);
if (k == 1) {
return nums[0];
}
else {
//利用k动态维护要弹出顶端元素的个数
for (int j = 1; j < k; j++) {
swap(nums[0], nums[n - j]);
//每弹一次都堆化(符合规范)
heapify(nums, n - j,0);
}
return nums[0];
}
}
};
三、最小堆
Time:O(nlogn)100ms
建堆:O(k);维护堆:O(nlogn)
class Solution {
public:
//堆排序(还是没用,提升速度而已)
void heap_Sort(vector<int> &sor, int n) {
for (int i = n - 1; i >=0; i--) {
swap(sor[i], sor[0]);
heapify(sor, i, 0);
}
for (int z = 0; z < n; z++) {
cout << sor[z] << " ";
}
cout << endl;
cout << "---------------------" << endl;
}
//堆化 数组 容量 堆化起点
void heapify(vector<int>&ify, int n, int i) {
if (i >= n) {
return;
}
int c1 = i * 2 + 1;
int c2 = c1 + 1;
int min = i;
if (c1 < n && ify[c1] < ify[min]) {
min = c1;
}
if (c2 < n && ify[c2] < ify[min]) {
min = c2;
}
if (min != i) {
swap(ify[i], ify[min]);
heapify(ify, n, min);
}
}
// 创建最小堆 数组 总容量 维护个数
vector<int> build_MinHeap(vector<int>&bui, int n, int k) {
//维护一个容量为k的最小堆
vector<int> kmin;
for (int i = 0; i < k; i++) {
//将原数组的值赋给最小堆
kmin.push_back(bui[i]);
}
//初始堆化
int partent = (k / 2) - 1;
for (int i = partent; i >= 0; --i) {
heapify(kmin, k, i);
}
//将数组的下一个值加入堆
for (int j = k; j < n; j++) {
kmin.push_back(bui[j]);
//堆化
int partent1 = (k+1 / 2) - 1;
for (int i = partent1; i >= 0; --i) {
heapify(kmin, k+1, i);
}
//将最小值换到末尾
swap(kmin[k], kmin[0]);
//堆化
heapify(kmin, k, 0);
//删除末尾
kmin.pop_back();
}
return kmin;
}
int findKthLargest(vector<int> &nums, int k) {
int n = nums.size();//6
auto kmin = build_MinHeap(nums, n, k);
return kmin[0];
}
};
四、快速排序
Time:O(nlogn)180ms
class Solution {
public:
//查找正在排序的元素的下标
int find_Pos(vector<int>&fin, int l, int h) {
int val = fin[h];
while (l < h) {
while (l<h && fin[l]>=val) {
l++;
}
fin[h] = fin[l];
while (l < h && fin[h] <= val) {
h--;
}
fin[l] = fin[h];
}
fin[l] = val;
return l;
}
//快速排序(大到小) 数组 起始下标 截止下标
void quike_Sort(vector<int>&qs, int l, int h) {
if (l < h) {
int pos = find_Pos(qs, l, h);
quike_Sort(qs, l, pos - 1);
quike_Sort(qs, pos + 1, h);
}
}
int findKthLargest(vector<int>&nums, int k) {
int n=nums.size();
quike_Sort(nums, 0, n-1);
return nums[k-1];
}
};
四点五、快速排序
Time:O(logn)8ms
随机选取数进行排序:O(logn)
class Solution {
public:
//查找正在排序的元素的下标
int find_Pos(vector<int>&fin, int l, int h) {
//随机选择一个下标与末尾交换
int ran = l+rand()% (h-l+1);///区间:l~h
swap(fin[ran], fin[h]);
int val = fin[h];
while (l < h) {
while (l < h && fin[l] >= val) {
l++;
}
fin[h] = fin[l];
while (l < h && fin[h] <= val) {
h--;
}
fin[l] = fin[h];
}
fin[l] = val;
return l;
}
//快速排序(大到小) 数组 起始下标 截止下标 所求下标
int quike_Sort(vector<int>&qs, int l, int h, int k) {
//leetcord中必须把判断语句删了,不然返回值错误
//if (l <= h) {
int pos = find_Pos(qs, l, h);
if (pos == k - 1) {
return qs[pos];
}
if (pos > k - 1) {
quike_Sort(qs, l, pos - 1, k);//左排序
}
else {
quike_Sort(qs, pos + 1, h, k);//右排序
}
//}
}
int findKthLargest(vector<int>&nums, int k) {
srand((unsigned int) time(NULL));
int n=nums.size();
return quike_Sort(nums, 0, n-1,k);
}
};
快速选择
Time:O(n)8ms
一个随机for
class Solution {
public:
// 容器 头节点 尾节点 索引
int quickSelect(vector<int>& a, int l, int r, int index) {
// 下标 容器 头节点 尾节点
int q = randomPartition(a, l, r);
if (q == index) {
return a[q];
} else {
// 下标是否小于索引 是:左递归 否:右递归
return q < index ? quickSelect(a, q + 1, r, index) : quickSelect(a, l, q - 1, index);
}
}
// 寻找下标 容器 头节点 尾节点
inline int randomPartition(vector<int>& a, int l, int r) {
// 在给定区间内随机选择一个下标
int i = rand() % (r - l + 1) + l;
// 交换选择的元素和末元素
swap(a[i], a[r]);
//所选择的元素在数组中的位置
return partition(a, l, r);
}
// 划分 容器 头节点 尾节点
inline int partition(vector<int>& a, int l, int r) {
// x是尾节点值 i是头节点减一
int x = a[r], i = l - 1;
// 从头节点减一开始 枚举至尾节点
for (int j = l; j < r; ++j) {
// 若枚举的元素 小于尾节点值
if (a[j] <= x) {
// 交换 此元素前的数组中第一个不符合该循环的元素(大于尾节点值)和当前枚举的元素
// 若此元素前的数组中没有第一个不符合该循环的元素,则不交换(交换自身)
swap(a[++i], a[j]);
}
}
// 交换前面都小于尾节点值得位置
swap(a[i + 1], a[r]);
// 返回该位置的下标
return i + 1;
}
int findKthLargest(vector<int>& nums, int k) {
srand(time(0));
return quickSelect(nums, 0, nums.size() - 1, nums.size() - k);
}
};