搜狗笔试题

1. 在Intel 多核CPU上, 以下多线程对int型变量x的操作,哪几个不是原子操作,假定变量的地址都是对齐的.

A. x=y     B. - -x   C. x-=1    D. x=-1  E.x-=y

2. 下面程序的输出结果:

#include <iostream>                 
using namespace std;                
class A{                            
    public:                         
        A(){}                       
        ~A(){}                      
        int f1(int a){              
            cout<<"Base f1";        
            return 0;               
        }                           
        virtual int g1(int a){      
            cout<<"Base g1 int";    
            return 0;               
        }                           
        int g1(short a){            
            cout<<"Base g1 short";  
            return 0;               
        }                           
};                                  
class B:public A{                   
    public:                         
        B(){}                       
        ~B(){}                      
        int f1(int a){              
            cout<<"Derived f1";     
            return 0;               
        }                           
        int g1(int a){              
            cout<<"Derived g1 int"; 
            return 0;               
        }                           
        virtual int g1(short a){    
            cout<<"Derived g1 short";
            return 0;               
        }                           
}; 
int main(){                         
    A* p1=new B;                    
    (*p1).g1(short(1));cout<<',';   
    p1->g1(1);cout<<',';            
    ((A)(*p1)).f1(1);cout<<'\n';    
    return 0;                       
}

输出结果为:

Base g1 short,Derived g1 int,Base f1

3. 虚函数是动态绑定的, 但是默认参数却是静态绑定的.

4.  稀疏矩阵

image

5. 假设AVL树有100个节点, 则其最大高度为:

7. 时间复杂度

image

8. Hash表

image

9.

image

10. 扔瓶子

image

有两个完全一样的瓶子,还有一幢100层的大楼。你想知道瓶子在哪一层会刚好摔碎(或者100层之内不碎),当然有可能从1层摔下就会碎,也有可能从100层摔下来也不会碎。但瓶子一旦摔碎就没法再使用了。现在要找一种方法,使得摔瓶子的次数最少。

正如原题中提到的那样,我们可以用一个瓶子,从1层开始,一层层试,这样肯定可以找到临界层,但最坏的情况是要摔100次才行。

很容易想到稍微好一些的方法:第一个瓶子从2层开始,尝试每个偶数层,直到摔碎(或者到100层也没碎,那问题就解决了),然后用剩下的一个瓶子尝试低一层,这样就可以解决问题。最坏的情况是临界层为99层,这样我们需要试51次才能得到答案,不过这已经比第一种方法好很多了。

如果我们把第一个瓶子每隔两层摔一次呢?会不会更少?

…………

先不要急着求解,让我们来想想摔瓶子需要遵守哪些原则

首先,不管用什么方法,都应该从低层向高层尝试吧?我想没有哪个人会直接把第一个瓶子从100层摔下来,因为一旦摔碎,我们就只剩下一个瓶子了。

注意,只剩下一个瓶子的时候,就只能从已经确定的“安全楼层”开始,一层一层往上试了。所以我们很容易想到,最佳策略应该是用第一个瓶子确定一个范围,然后用第二个瓶子穷举。其实之前提到的摔偶数层的方法就是用的这个思想。

用规范一点的语言表述,就是:

如果第一个瓶子在a层没有摔碎,紧接着下一次尝试在b层(b>a)摔碎了,那么我们必须要用第二个瓶子从(a+1)层开始一层层往上试,直至摔碎,该层就是临界层。当然,如果到(b-1)层还没有碎,那么我们就知道临界层是b层了。

由于我们的策略必须要保证能找到临界层,所以我们必须以最坏情况最为衡量策略优劣的标准。我们要做的是就是把最坏情况的尝试次数降到最低。

我们来举一个例子:如果是把第一个瓶子从50层扔下来(可以说是二分法思想),会有两种情况:如果碎了,那么就必须把另一个瓶子从1楼开始试起,这种情况的最坏情况是临界层为49层或50层,需要试50次;如果没碎,这个时候我们还可以继续二分,把瓶子从75层摔下,如果碎了,那么就要从51层试起,“最坏情况”是要试到74层,总共要试26次……

当然,我们最终只有一个“最坏情况”,也就是50次,像26次这样的只能称作是“极坏情况”。

容易看出,就算极坏情况的尝试次数再少,最坏情况才是评判的标准。如果可以让最坏情况的尝试次数减少,哪怕极坏情况尝试的次数稍微增加也没问题。所以我们要做的是:

让所有的极坏情况和最坏情况的尝试次数尽可能接近。

由于第一个瓶子是用来确定穷举范围,每试一次,次数都要加1,那么为了使得总次数尽可能接近,确定的穷举范围就要少1。

于是1+2+3+…+14=105>100,所以我们第一个瓶子从14层开始摔,假如没碎的话就到27(14+13)层,然后是39(14+13+12)层,然后层数分别为50、60、69、77、84、90、95、99、100。当瓶子摔碎的时候,我们就可以知道一个范围,然后开始穷举,这样极坏情况和最坏情况都是14次!

这就是最佳方案!

当然,我是不会满足解决两个瓶子的问题的,我开始想3个瓶子的情况。后来发现3个瓶子的问题也是同样的思路:前两个瓶子用来测定范围,最后一个瓶子用来穷举。只不过数列不是1+2+3…这样,而是1+(1+2)+(1+2+3)+…+(1+2+3+4+5+6+7+8)=120>100。于是第一个从36(1+2+3+4+5+6+7+8)层摔,然后如果没碎就从64(36+1+2+3+4+5+6+7)层摔,以此类推,如果碎了就转化成了两个瓶子的问题。

参考: http://hi.baidu.com/simonkuang26/item/2572e8fd16c3066e3d14853c

11. 方格取数

image

12. 八哥送信

image

原文地址:https://www.cnblogs.com/xkfz007/p/2766990.html