方法一:冒泡排序返回倒数第K个元素
class Solution {
public int findKthLargest(int[] nums, int k) {
int n = nums.length,temp;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
return nums[n-k];
}
}
方法二 快速排序:
class Solution {
int Partition(int[] A, int low, int high) {
int pivot = A[low];
while (low < high) {
while (low < high && A[high] >= pivot)
--high;
A[low] = A[high];// 将比枢轴小的元素移动到左端
while (low < high && A[low] <= pivot)
++low;
A[high] = A[low];// 将比枢轴大的元素移动到右端
}
A[low] = pivot;// 枢轴元素存放到最终位置
return low;// 返回存放枢轴的最终位置
}
void QuickSort(int[] A, int low, int high) {
if (low < high) {// 递归跳出条件 下面一个方法可以没有这句话
int pivot = Partition(A, low, high);// 划分
QuickSort(A, low, pivot - 1);
QuickSort(A, pivot + 1, high);
}
}
public int findKthLargest(int[] nums, int k) {
int n = nums.length;
QuickSort(nums, 0, n - 1);
return nums[n - k];
}
}
方法三 快速选择排序:
利用一趟快速排序可以确定一个元素的最终位置,只需要找到最终位置就可以了,所以不需要全排序完
class Solution {
int Partition(int[] A, int low, int high) {
int pivot = A[low];
while (low < high) {
while (low < high && A[high] >= pivot)
--high;
A[low] = A[high];// 将比枢轴小的元素移动到左端
while (low < high && A[low] <= pivot)
++low;
A[high] = A[low];// 将比枢轴大的元素移动到右端
}
A[low] = pivot;// 枢轴元素存放到最终位置
return low;// 返回存放枢轴的最终位置
}
int QuickSort(int[] A, int low, int high, int k) {
int pivot = Partition(A, low, high);// 划分
if (pivot < A.length - k) {//最终位置在枢轴右边->到枢轴右边找
return QuickSort(A, pivot + 1, high, k);
} else if (pivot == A.length - k) {
return pivot;//递归跳出条件
} else {//最终位置在枢轴左边->到枢轴左边找
return QuickSort(A, low, pivot - 1, k);
}
}
public int findKthLargest(int[] nums, int k) {
int n = nums.length;
QuickSort(nums, 0, n - 1, k);
return nums[n - k];
}
}
方法四 堆排序 优化 只排了前k个最大的元素
class Solution {
void BuildMaxHeap(int[] A, int length) {// 建堆
for (int i = length / 2; i >= 0; i--) {
HeadAdjust(A, i, length);
}
}
void HeadAdjust(int[] A, int k, int length) {// 和王道不一样下标从0开始算
// 函数HeadAdjust将元素为k的子树进行调整
int temp = A[k];// temp暂存子树根结点
for (int i = 2 * k + 1; i <= length - 1; i = i * 2 + 1) {// 从k的第一个孩子2k+1开始比较
if (i + 1 < length && A[i] < A[i + 1])// 如果右孩子大
i++;
if (temp > A[i])// 根最大不用调整,上面i++后的话,现在的A[i]就是刚才的i+1
break;
else {
A[k] = A[i];// 将A[i]调整到双亲结点上
k = i;// 将i赋值给k,现在的k就是刚才的孩子结点
}
}
A[k] = temp;// 双亲结点调整到孩子结点
}
void HeapSort(int[] A, int length,int k) {
BuildMaxHeap(A, length);// 先建堆
for (int i = length - 1; i >= length-k; i--) {//只输出前k个堆顶
int temp = A[0];// 堆顶和最后一个元素交换
A[0] = A[i];
A[i] = temp;
HeadAdjust(A, 0, i);// 调整堆
}
}
public int findKthLargest(int[] nums, int k) {
HeapSort(nums,nums.length,k);
return nums[nums.length-k];
}
}