1、两个有序数组中第k大的数
int findKth(vector<int> nums1, vector<int> nums2, int k){
int s1 = nums1.size();
int s2 = nums2.size();
if (s1 > s2)
return findKth(nums2, nums1, k);
if (s1 == 0)
return nums2[k - 1];
if (k == 1)
return min(nums1[0], nums2[0]);
int i = min(k / 2, s1), j = k - i;
if (nums1[i - 1] < nums2[j - 1])
return findKth(vector<int>(nums1.begin() + i, nums1.end()), nums2, k - i);
else if (nums1[i - 1] > nums2[j - 1])
return findKth(nums1, vector<int>(nums2.begin() + j, nums2.end()), k - j);
else
return nums1[i - 1];
}
2、在N个乱序数组中查找第k大的数
不对前K个数进行排序 + 不对N-k个数排序,可以使用
思路:寻找第K个大元素。
具体方法:使用类似快速排序,执行一次快速排序后,每次只选择一部分继续执行快速排序,直到找到第K个大元素为止,此时这个元素在数组位置后面的元素即所求
时间复杂度:
若随机选取枢纽,线性期望时间O(N)
若选取数组的“中位数的中位数”作为枢纽,最坏情况下的时间复杂度O(N)
利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。
利用快排的partion思想 T(n) = 2T(n/2) + O(1) 时间复杂度为O(n)
该方法只有当我们可以修改输入的数组时可用,位于数组左边的k个数字就是最小的k个数字(但这k个数字不一定是排序的),位于第k个数右边的数字都比第k个数字大
#include<iostream>
#include<stdio.h>
using namespace std;
int Partition (int *L, int low, int high)
{
int temp = L[low];
int pt = L[low]; //哨兵
while (low != high)
{
while (low < high && L[high] >= pt)
high--;
L[low] = L[high];
while (low < high && L[low] <= pt)
low++;
L[high] = L[low];
}
L[low] = temp;
return low;
}
void QSort (int *L, int low, int high) //快速排序
{
int pl;
if (low < high)
{
pl = Partition (L,low,high);
QSort (L, low, pl-1);
QSort (L, pl+1, high);
}
}
void findk(int k,int *L,int low,int high)
{
int temp;
temp=Partition(L,low,high);
if(temp==k-1)
{
cout<<"第"<<temp+1<<"大的数是:"<<L[temp]<<endl;
}
else if(temp>k-1)
findk(k,L,low,temp-1);
else
findk(k,L,temp+1,high);
}