腾讯面试题:tcp三次握手的过程,accept发生在三次握手哪个阶段?
答accept发生在三次握手之后。
第一次握手:客户端发送syn包(syn=j)到服务器。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个ASK包(ask=k)。
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1)。
三次握手完成后,客户端和服务器就建立了tcp连接。这时可以调用accept函数获得此连接。
const的含义及实现机制,比如:constinti,是怎么做到i只可读的?
const用来说明所定义的变量是只读的。
这些在编译期间完成,编译器可能使用常数直接替换掉对此变量的引用。
用UDP协议通讯时怎样得知目标机是否获得了数据包
可以在每个数据包中插入一个唯一的ID,比如timestamp或者递增的int。
接收方在收到数据后将ID再发给发送方作为回应。
一天总共有3600*24=86400秒。
定义一个长度为86400的整数数组intdelta[86400],每个整数对应这一秒的人数变化值,可能为正也可能为负。开始时将数组元素都初始化为0。
这样处理一遍后数组中存储了每秒中的人数变化情况。
定义另外一个长度为86400的整数数组intonline_num[86400],每个整数对应这一秒的论坛在线人数。
假设一天开始时论坛在线人数为0,则第1秒的人数online_num[0]=delta[0]。第n+1秒的人数online_num[n]=online_num[n-1]+delta[n]。
在一个文件中有10G个整数,乱序排列,要求找出中位数。内存限制为2G。
不妨假设10G个整数是64bit的。
2G内存可以存放256M个64bit整数。
我们可以将64bit的整数空间平均分成256M个取值范围,用2G的内存对每个取值范围内出现整数个数进行统计。这样遍历一边10G整数后,我们便知道中数在那个范围内出现,以及这个范围内总共出现了多少个整数。
如果中数所在范围出现的整数比较少,我们就可以对这个范围内的整数进行排序,找到中数。如果这个范围内出现的整数比较多,我们还可以采用同样的方法将此范围再次分成多个更小的范围(256M=2^28,所以最多需要3次就可以将此范围缩小到1,也就找到了中数)。
两个整数集合A和B,求其交集。
1.读取整数集合A中的整数,将读到的整数插入到map中,并将对应的值设为1。
2.读取整数集合B中的整数,如果该整数在map中并且值为1,则将此数加入到交集当中,并将在map中的对应值改为2。
通过更改map中的值,避免了将同样的值输出两次。
2.也可以将A和B分别排序,然后利用归并的思想搞定。
有1到10w这10w个数,去除2个并打乱次序,如何找出那两个数?
申请10w个bit的空间,每个bit代表一个数字是否出现过。
开始时将这10w个bit都初始化为0,表示所有数字都没有出现过。
然后依次读入已经打乱循序的数字,并将对应的bit设为1。
当处理完所有数字后,根据为0的bit得出没有出现的数字。
首先计算1到10w的和,平方和。
然后计算给定数字的和,平方和。
两次的到的数字相减,可以得到这两个数字的和,平方和。
所以我们有
x+y=n
x^2+y^2=m
解方程可以得到x和y的值。
有1000瓶水,其中有一瓶有毒,小白鼠只要尝一点带毒的水24小时后就会死亡,至少要多少只小白鼠才能在24小时时鉴别出那瓶水有毒?
最容易想到的就是用1000只小白鼠,每只喝一瓶。但显然这不是最好答案。
既然每只小白鼠喝一瓶不是最好答案,那就应该每只小白鼠喝多瓶。那每只应该喝多少瓶呢?
首先让我们换种问法,如果有x只小白鼠,那么24小时内可以从多少瓶水中找出那瓶有毒的?
由于每只小白鼠都只有死或者活这两种结果,所以x只小白鼠最大可以表示2^x种结果。如果让每种结果都对应到某瓶水有毒,那么也就可以从2^x瓶水中找到有毒的那瓶水。那如何来实现这种对应关系呢?
第一只小白鼠喝第1到2^(x-1)瓶,第二只小白鼠喝第1到第2^(x-2)和第2^(x-1)+1到第2^(x-1)+2^(x-2)瓶....以此类推。
回到此题,总过1000瓶水,所以需要最少10只小白鼠。
根据上排给出十个数,在其下排填出对应的十个数,要求下排每个数都是上排对应位置的数在下排出现的次数。上排的数:0,1,2,3,4,5,6,7,8,9。
0,1,2,3,4,5,6,7,8,9
6,2,1,0,0,0,1,0,0,0
通过一个循环做,三次循环搞定.
任意0-N,都是N-3的位置是1,前面是N-4,2,1,其他是0
给40亿个不重复的unsignedint的整数,没排过序的,然后再给几个数,如何快速判断这几个数是否在那40亿个数当中
unsignedint的取值范围是0到2^32-1。我们可以申请连续的2^32/8=512M的内存,用每一个bit对应一个unsignedint数字。首先将512M内存都初始化为0,然后每处理一个数字就将其对应的bit设置为1。当需要查询时,直接找到对应bit,看其值是0还是1即可。
IBM面试题:c++中引用和指针有什么不同?指针加上什么限制等于引用?
引用不是一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。引用一经确定就不能修改。
指针是一个变量,需要在内存中分配空间,此空间中存储所指对象的地址。由于指针是一个普通变量,所以其值还可以通过重新赋值来改变。
把指针定义为const后,其值就不能改变了,功能和引用类似,但有本质的区别。
谷歌面试题:1024!末尾有多少个0?
末尾0的个数取决于乘法中因子2和5的个数。显然乘法中因子2的个数大于5的个数,所以我们只需统计因子5的个数。
是5的倍数的数有:1024/5=204个
是25的倍数的数有:1024/25=40个
是125的倍数的数有:1024/125=8个
是625的倍数的数有:1024/625=1个
所以1024!中总共有204+40+8+1=253个因子5。
也就是说1024!末尾有253个0。
谷歌面试题:给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数
只要我们可以从n个数中随机选出1到n个数,反复进行这种运算,直到剩下最后一个数即可。
我们可以调用n次给定函数,生成n个1到5之间的随机数,选取最大数所在位置即可满足以上要求。
例如
初始的7个数[1,2,3,4,5,6,7].
7个1到5的随机数[5,3,1,4,2,5,5]
那么我们保留下[1,6,7],
3个1到5的随机数[2,4,1]
那么我们保留下[6]
6就是我们这次生成的随机数。
产生K个数(k>1)假定产生的数分别为n1,n2,n3,n4...
那么定义产生的数为n1-1+(n2-2)*5+(n3-1)*5^2+(n4-1)*5^3........
于是产生的数位于区间(0,5^k-1)
然后把5^k分成k等分,产生的数位于哪个等分就是那个产生的随机数(0~6),然后+1即可
如果位于k等分的余数范围,则重新执行一次上述过程
不用担心余数问题,当k取3时落到余数范围的概率就已经降低为6/125
判断一个自然数是否是某个数的平方。当然不能使用开方运算。
假设待判断的数字是N。
方法1:
遍历从1到N的数字,求取平方并和N进行比较。
如果平方小于N,则继续遍历;如果等于N,则成功退出;如果大于N,则失败退出。
复杂度为O(n^0.5)。
方法2:
使用二分查找法,对1到N之间的数字进行判断。
复杂度为O(logn)。
方法3:
由于
(n+1)^2
=n^2+2n+1,
=...
=1+(2*1+1)+(2*2+1)+...+(2*n+1)
注意到这些项构成了等差数列(每项之间相差2)。
所以我们可以比较N-1,N-1-3,N-1-3-5...和0的关系。
如果大于0,则继续减;如果等于0,则成功退出;如果小于0,则失败退出。
复杂度为O(n^0.5)。不过方法3中利用加减法替换掉了方法1中的乘法,所以速度会更快些。
给定一个未知长度的整数流,如何随机选取一个数?
方法1.
将整个整数流保存到一个数组中,然后再随机选取。
如果整数流很长,无法保存下来,则此方法不能使用。
方法2.
如果整数流在第一个数后结束,则我们必定会选第一个数作为随机数。
如果整数流在第二个数后结束,我们选第二个数的概率为1/2。我们以1/2的概率用第2个数替换前面选的随机数,得到满足条件的新随机数。
....
如果整数流在第n个数后结束,我们选第n个数的概率为1/n。我们以1/n的概率用第n个数替换前面选的随机数,得到满足条件的新随机数。
利用这种方法,我们只需保存一个随机数,和迄今整数流的长度即可。所以可以处理任意长的整数流。
1.使用数组存储。
2.使用排序数组存储。
获得中数时,在O(1)复杂度内找到中数。
3.使用大根堆和小根堆存储。
使用大根堆存储较小的一半数字,使用小根堆存储较大的一半数字。
谷歌面试题:在一个特殊数组中进行查找
给定一个固定长度的数组,将递增整数序列写入这个数组。当写到数组尾部时,返回数组开始重新写,并覆盖先前写过的数。请在这个特殊数组中找出给定的整数。
假设数组为a[0,1,...,N-1]。
我们可以采用类似二分查找的策略。