排序
题目
题目描述
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
输入输出
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
排序
快速排序
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
quickSort(nums, 0, nums.size() - 1);
return nums[nums.size() - k];
}
void quickSort(vector<int>& nums, int l, int r){
if(l < r){
int mid = partion(nums, l, r);
quickSort(nums, l, mid -1);
quickSort(nums, mid + 1, r);
}
}
int partion(vector<int>& nums, int l , int r){
int randIndex = rand()%(r-l+1)+l;
swap(nums[l], nums[randIndex]);
int temp = nums[l];
while(l < r){
while(l < r && nums[r] > temp)r--;
nums[l] = nums[r];
while(l < r && nums[l] <= temp)l++;
nums[r] = nums[l];
}
nums[l] = temp;
return l;
}
};
归并排序
public void mergeSort(int[] nums, int l,int r){
if(l < r){
int mid = (l + r) /2;
mergeSort(nums, l, mid);
mergeSort(nums, mid + 1, r);
merge(nums,l , mid,mid + 1, r);
}
return;
}
public void merge(int[] nums, int l1,int r1, int l2,int r2){
int i = l1, j = l2;
int[] temp = new int[2*(r1 - l1) + 2];
int index = 0;
while(i <= r1 && j <= r2){
if(nums[i] <= nums[j]) temp[index++] = nums[i++];
else temp[index++] = nums[j++];
}
while(i <= r1) temp[index++] = nums[i++];
while(j <= r2) temp[index++] = nums[j++];
for(int k = 0 ; k < index; k++){
nums[l1 + k] = temp[k];
}
}
堆排序
使用数组下标从0开始,对于下标 i :父节点( i - 1)/ 2;
左子节点 2 i + 1,右子节点 2 i + 2。
从倒数第二层即找到最后一个节点(n - 1)的父节点(n-2)/2开始依次往右往上堆化。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size();
for(int i = (n-2) / 2; i>= 0; i--)
sort(nums, i, n); //从最后一个节点父节点往左往上堆化
for(int i = n- 1; i >= 1; i--){
swap(nums[0],nums[i]); //把最大值交换到末尾,继续进行堆化
sort(nums, 0 ,i);
}
return nums[nums.size() - k];
}
void sort (vector<int>& nums, int i , int n){
int r = 2 * i + 2;
int l = r -1;
int max = i;
if(l < n && nums[l] > nums[max]) max = l;
if(r < n && nums[r] > nums[max]) max = r;
if(max != i){ //nums[i] 比左右子节点小是需要交换
swap(nums[max],nums[i]);
sort(nums, max, n); //递归进行
}
}
};
由于只需要得到最大的K,并不需要对整个数组都进行排序,在快排的基础上改进
快速选择
每次选择一个元素划分左右区间,只需要关心比他大的元素,k修改为nums.size() - k,即完全排序后第k大所在的位置,当当前位置j小于k时l = j + 1,大于k时 r = j - 1.
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
k = nums.size() - k;
int l = 0, r = nums.size() - 1;
while(l < r){
int j = sort(nums,l,r);
if(j == k)
break;
else if(j < k)
l = j + 1;
else
r = j - 1;
}
return nums[k];
}
int sort(vector<int>& nums, int l, int r){
int randIndex = rand()%(r-l+1)+l;
swap(nums[l], nums[randIndex]);
int k = r;
for(int i = r; i > l; i--){
if(nums[i] >= nums[l])
swap(nums[i],nums[k--]);//从r往前到k + 1前存放比nums[l]大的
}
swap(nums[l],nums[k]);
return k;
}
};