【C++】面试101,寻找第K大,数据流中的中位数,数组中出现次数超过一半的数字,字符串中找出连续最长的数字串

目录

1.寻找第K大

2.数据流中的中位数

3.数组中出现次数超过一半的数字

 4.字符串中找出连续最长的数字串


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;
}

猜你喜欢

转载自blog.csdn.net/weixin_71138261/article/details/129701462