400字范文,内容丰富有趣,生活中的好帮手!
400字范文 > 名企笔试:腾讯招聘笔试(微信红包)

名企笔试:腾讯招聘笔试(微信红包)

时间:2024-02-21 07:00:06

相关推荐

名企笔试:腾讯招聘笔试(微信红包)

名企笔试:腾讯招聘笔试(微信红包)

题目描述

春节期间小明使用微信收到很多个红包,非常开心。在查看领取红包记录时发现,某个红包金额出现的次数超过了红包总数的一半。请帮小明找到该红包金额。写出具体算法思路和代码实现,要求算法尽可能高效。

给定一个红包的金额数组gifts及它的大小n,请返回所求红包的金额。

若没有金额超过总数的一半,返回0。

测试样例:

[1,2,3,2,2],5

返回:

2

分析:

找到出现一般的超过红包,就是找到超过一半的数,若没有超过一半的数就返回0。

想法一、排序,返回中位数,然后计算中位数的个数,如果超过一半就返回,否则返回0。时间复杂度是O(nlog(n))+O(n):排序+遍历一遍确定是否是超过一半的数。空间复杂度O(1)。

想法二、使用hash函数,计算每一个数出现的次数,然后便利hash表,返回个数超过一半的数。时间复杂度O(n);分别是计数+遍历hash表+验证。空间复杂度O(n)。

想法三、如果一个数出现次数超过一半,我们任意去掉两个不相同的数,剩下的数组中,仍然有一个数出现的次数是剩下数组的一半。假设出现一半的数是a,我们每次去掉两个不相同的数b和c。如果b!=a且c!=a,那么剩下的数然后是a超过剩余数组的一半。假如a=b,我们去掉两个数,count[a] = k > n/2;去电b和c后数组长度n-2;count(a)=k-1 > n/2 – 1 = (n-2)/2。

我们编程的时候是否每次都要删除两个不同的数呢?删除数组中的数的时间复杂度是O(n)。时间 复杂度更高。其实我们可以用计数来使用这个思想。第一至k=1,标记a=A[1];(A是一个数组,长度是n)。遍历一遍数组,如果有A[i] = a; k+=1;

else: k -=1;当出现k=0时证明前一个候选的值不是超过一半的数,因此另k=1;a = A[i]

直到最后结束,得到a。确定a的个数是否大于一半即可。时间复杂度O(n);计数+验证。空间复杂度O(1)。

Code:

#include<iostream>#include<stdio.h>#include<map>#include<algorithm>using namespace std;//这里的测试数据默认是a数组int a[] = {1,2,3,2,2};//int a[] = {1,2,3,4,5};bool isThisDigit(int res,int n){int k = 0;for(int i=0;i<n;i++){if(res == a[i]) k++;}return k > n/2;}//排序+验证int test1(int n){sort(a,a+n);int result = a[n/2];//验证if(isThisDigit(result,n)) return result;else return 0; }int test2(int n){map<int,int> cnt;for(int i=0;i<n;i++){cnt[a[i]] ++;}map<int,int>::iterator it;int result = 0,k = 0;for(it = cnt.begin();it!=cnt.end();++it){if(it->second > k){result = it -> first;k = it->second;}}if(isThisDigit(result,n)) return result;else return 0;}int test3(int n){int result=a[0],k=1;for(int i=1;i<n;i++){if(a[i] == result) k++;else k--;if(k==0){//更新候选值result = a[i];k = 1;}}if(isThisDigit(result,n)) return result;else return 0;}int main(){cout<<test1(5)<<endl;cout<<test2(5)<<endl;cout<<test3(5)<<endl;return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。