目录
1.寻找第K大
找最大肯定建小堆,先把前K建小堆,然后剩下的比较,如果有更大,进优先级队列 ,最后队列顶就是第K大
int findKth(vector<int> a, int n, int K) {
// write code here
priority_queue <int, vector<int>, greater<int>> pq;
for (int i = 0; i < K; i++)
{
pq.push(a[i]);
}
for (int i = K; i < n; i++)
{
if (a[i] > pq.top())
{
pq.pop();
pq.push(a[i]);
}
}
return pq.top();
}
2.数据流中的中位数
首先我们分析一下题意,暴力算法是可以的,直接把每一个数都存到vector,然后排序,中位数就是最中间的一个数,如果个数是偶数个,那就是两个数的平均值(注意看小数点)
还有更好的方法,利用中位数定义,就是最中间的那个数字
所以可以划分区间
[0,mid-1][mid][mid+1,end]
如果左区间的个数==右区间个数,直接返回(第一个区间的最大值+第二个区间最小值)/2.0
那怎么找一个区间的最大值/最小值(以插入/搜索的最小的时间复杂度)
可以建堆!
那么左边应该找最大值(堆顶元素),建大堆
右边找最小值(堆顶元素),建小堆
那么怎么插入元素,我们要维持两个堆的结构:数目相差不超过1 && 左区间的数据不能比右区间值大
class Solution {
public:
priority_queue<int> left; //左区间的堆(对应大堆),优先级队列默认大堆
priority_queue<int,vector<int>,greater<int>> right;//右区间,对应小堆
void Insert(int num) {
//规定左区间的数目比右区间少1或者相等(或者规定右区间少一也可,只是方便理解)
if((left.size()+right.size())& 1) { //左区间和右区间总个数是奇数的意思
if(!left.empty() && num<left.top()) //这个值就是左区间的值(因为他比大根堆顶小),但是由于左右区间的总个数是奇数,也就是左区间已经和右区间不相等(根据规定,左区间比右区间少一/相等,但是这个数字还必须是左区间的必须插入左区间内),此时不能改变这种平衡,所以要把左区间最大的数挤到右区间
{
left.push(num);//把这个数字压进去,找到里面最大的 这个最大的应该被挤到右区间
right.push(left.top());//这个数字应该插入右区间(保证左<右)
left.pop();
}
else {
right.push(num); //左是空(根据规定,左比右少1/相等,如果此时入了左,破坏结构)或者num比左边top()还大(应到右区间)
}
}
else //此时左右区间总个数是偶数,证明两个区间个数相等,由于左比右小1,所以优先考虑把数字插入右
{
if(!right.empty() && num>right.top()) //右不是空,并且这个数字应该在右
{
right.push(num); //和上面一样的做法
left.push(right.top());
right.pop();
}
else {
left.push(num);
}
}
}
double GetMedian() {
if(left.size()==right.size()) //左右相等个数,那么加上最中间的元素,整个数组是奇数个,中位数是平均值
return (left.top()+right.top())/2.0;
else if(left.size()>right.size()) //左边区间个数更多,中位数在左
return left.top();
else
return right.top();//否则在右
}
};
3.数组中出现次数超过一半的数字
出现次数都超过一半,那么肯定在最中间
可以用映射表的思想去解
int MoreThanHalfNum_Solution(vector<int> numbers) {
int a[10001]={0};
for(int i=0;i<numbers.size();i++)
{
a[numbers[i]]++;
if(a[numbers[i]]>(numbers.size()/2))
return numbers[i];
}
return 0;
}
或者排序之后,统计numbers[mid]出现次数
int MoreThanHalfNum_Solution(vector<int> numbers) {
// int a[10001]={0};
// for(int i=0;i<numbers.size();i++)
// {
// a[numbers[i]]++;
// if(a[numbers[i]]>(numbers.size()/2))
// return numbers[i];
// }
int mid = numbers.size() / 2;
int count;
sort(numbers.begin(), numbers.end());
for (int i = 0; i < numbers.size(); i++)
{
if (numbers[i] == numbers[mid])
count++;
}
if (count > mid)
return numbers[mid];
return 0;
}
4.字符串中找出连续最长的数字串
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str,res,cur;
cin>>str;
for(int i=0;i<=str.length();i++){
if(str[i]>='0' && str[i]<='9')cur+=str[i];
else{
if(res.length()<cur.length())res=cur;
cur="";
}
}
cout<<res;
return 0;
}