zoukankan      html  css  js  c++  java
  • 腾讯研发工程师笔试题(整理)

    腾讯研发工程师笔试题

    1.爸爸去哪儿中的3对父子站成一排,各自父子之间不能相邻,比如石头不能和郭涛挨着,以此类推,共有几种站法?

      A.120

      B.48

      C.240

      D.144

    分析:答案为C。

    解题方法1:假设三对父子分别是Aa、Bb、Dd;

    第一个位置有6种选择,假设为A;
    第二个位置有4种选择(因为不能为a),假设为B;
    第三个位置需要分类讨论一下,如果为a,则可以确定后面三位只有两种选择了,如果不为a,第三个位置有两种选择(D和d),假设为D,进而再确定后面三个位置的选择数。
    那么结果是:6*4*(2+2*4)=240。
    解题方法2:容斥原理,6个人全排列-一对父子相邻+两对父子相邻-三队父子相邻 
    A(6,6)-C(3,1)*A(2,2)*A(5,5) + C(3,2)*A(4,4)*A(2,2)*A(2,2) - A(3,3)*A(2,2)*A(2,2)*A(2,2) = 240
    解题方法3:易理解的办法:
    (1)先取出两对父子,3对父子取出2对有C(3,2)=3种,
    (2)进行排序,保证父子不相邻,就有 2*2=4种排序
    (3)剩下一对父子插入上面4个人的5个缝隙中,就有 A(5,2)=5*4=20
    (4)3*4*20=240
     
    2、请找出下面程序中有哪些错误:
    int main()
    {
       int i=10;
       int j=1;
       const int *p1;//(1)
       int const *p2=&i; //(2)
       p2=&j;//(3)
       int *const p3=&i;//(4)
       *p3=20;//(5)
       *p2=30;//(6)
       p3=&j;//(7)
    return 0;
    }
    

          A.1,2,3,4,5,6,7

      B.1,3,5,6

      C.6,7

      D.3,5

    分析:答案为C。

    (1)const int*p1:表示不能通过指针p1修改它指向的内存单元的值,但是p1本身可修改。

    (2)int const*p2=&i:与p1相同,即不能修改p2指向的内存单元的值,但是可以修改p2使其指向其它的内存单元。这里p2指向了整型变量i
    (3)p2=&j:修改p2,使其指向整型变量 j ,由(2)可知(3)没错。
    (4)int *constp3=&i:p3本身是指向整型变量的常指针,即p3初始化后不能再指向其它的内存单元,但是可以修改p3指向的内存单元的值。这里p3指向了整型变量i。
    (5)*p3=20:通过p3将变量i的值修改为2,由(4)可知(5)没错。
    (6)*p2=30:通过p2修改它所指向的内存单元的值,由(2)可知(6)错误。
    (7)p3=&j:修改p3,使其指向j,由(4)可知(7)错误。

    3、以下代码输出什么____.  

    main()
    {
       int a[5]={1,2,3,4,5};
       int *p=(int *)(&a+1);
       printf("%d",*(p-1));
    }
    

        A.1

      B.2

      C.5

      D.出现错误

    分析:答案:C。

    数组名a可以作为数组的首地址,而&a是数组的指针,那么&a+1就是表示一个指向大小为5的下一个数组的指针,也就是数组a最后一个元素的下一个位置,那么int*p=(int*)(&a+1)进行强制类型转换,将指向数组的指针转换为指向第二个数组中首元素的指针,所以p-1则是指向第一个数组中最后一个元素的指针,所以输出是5。

    5、有如下C++代码:

    struct A{
      void foo(){printf("foo");}
      virtual void bar(){printf("bar");}
      A(){bar();}
    };
    struct B:A{
      void foo(){printf("b_foo");}
      void bar(){printf("b_bar");}
    };
    

      那么

    A *p=new B;
    p->foo();
    p->bar();
    

      输出为:

          A.barfoob_bar

      B.foobarb_bar

      C.barfoob_foo

      D.foobarb_fpp

    分析:答案:A

    A *p=newB;// A类指针指向一个实例化对象B, B类继承A类,先调用父类的无参构造函数,bar()输出bar,B类没有自己显示定义的构造函数。

    p->foo();//执行B类里的foo()函数,因为foo不是虚函数,所以直接调用父类的foo函数,输出foo
    p->bar();//执行B类的bar()函数, 该函数为虚函数,调用子类的实现,输出b_bar

    6、linux下,指定文件file1为所有用户可读,可写,可执行,执行命令:___1__。修改file1的拥有者为test,拥有组为user,执行命令:___2__。

      A.chmod 776,chown test

      B.chmod 777,chown user

      C.chmod 777,chown test

      D.chmod 778,chown user

    分析:答案:C。

    # 改变权限
    chmod 777 filepath
    # 改变所有者
    chown test filepath 
    # 改变所属组
    chgrp user filepath
     
    7、(不定项)哪些设计模式是降低资源使用率:

      A.prototype

      B.singleton

      C.flyweight

      D.abstract factory

    分析:答案:BC

    ---单例模式肯定降低了资源使用率,保证该类的实例永远只有一个!

    ---原型模式适用于在初始化信息不发生变换的情况,克隆的方法比较适合,主要的目的是避免重新初始化对象,如果后面需要对新对象进行,还需要区分深拷贝和浅拷贝。无论是深拷贝还是浅拷贝只是复制了资源,并没有降低资源使用率。

    ---享元模式(Flyweight): 基于共享技术用于把一些共同的信息(或模块)抽象出来,避免了大量相似类的开销,也降低了资源的使用率。

    ---抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。

    9、n个顶点,m条边的全连通图,至少去掉____边才能构成一棵树?

      A.n-1

      B.m-1

      C.m-n+1

      D.m-n-1

    分析:答案:C。

    由于n个顶点的树一定有n-1条边,所以需要去掉m-(n-1)=m-n+1条边。

    10、10.在序列(22,34,55,77,89,93,99,102,120,140)中,采用二分查找,分别查找77,34,99,所需的查找次数分别为()

      A.3,3,3

      B.3,3,4

      C.3,4,3

      D.4,2,4

    分析:答案:D。

    22 34 55 77 89 93 99 102 120 140

    0   1    2   3  4    5   6     7    8     9
    假设低下标用low表示,高下标用high表示。
    查找77:
    开始low = 0, high = 9
    第一次查找,找到中心的下标为(0+9)/2 = 4,即89,由于89大于77,所以,调整low = 0,high = 3(注意:由于知道下标为4的元素比77大,所以不会让high等于4,即二分法 mid是要判断大小进行加1或减1,再运算的)
    第二次查找,找到中心的下标为(0+3)/2 = 1,即34,由于34小于77,所以,调整low = 2,high = 3
    第三次查找,找到中心的下标为(2+3)/2 = 2,即55,由于55小于77,所以,调整low = 3,high = 3
    第四次查找,找到中心的下标为(3+3)/2 = 3,即77,找到所要找的元素
     
    查找34和99的过程类似。。。
     
    11、ip地址10.1.8.0/24和10.1.9.0/24,下列哪个是正确的汇总网段:

      A.10.0.0.0/8

      B.10.1.0.0/16

      C.10.1.8.0/23

      D.10.1.10.0/24

    分析:答案:C。

    从第一位不同的开始往后全为0;后面位相同的前缀位的位数

    10.1.8.0/24 == 10.1.  0000 100 0 .0/24
    10.1.9.0/24 == 10.1.  0000 100 1 .0/24
    从不同的位开始,替换为0,得
                            10.1.  0000 100 0  .0 = 10.1.8.0
    子网掩码为       8+8           +7          =23位
    所以汇总网段为10.1.8.0/23
     
    12、以下代码是否完全正确,执行可能得到的结果是____。
    class A{
       int i;
    };
    class B{
       A *p;
    public:
       B(){p=new A;}
       ~B(){delete p;}
    };
    void sayHello(B b){
    }
    int main(){
       B b;
       sayHello(b);
    }
    

      A.程序正常运行

      B.程序编译错误

      C.程序崩溃

      D.程序死循环

    分析:答案:C。

    class A{
       int i;
    };
    class B{
       A *p;
    public:
       B(){p=new A;}
       ~B(){delete p;}
       /*
       B(const B& ths){
           p = ths.p;
       }*/
    };
    void sayHello(B x){
    }
    int main(){
       B b;
       sayHello(b);
    }
    

    这里的错误原因是编译器在生成default copy construction的时候使用的bitwise copy语义,也就是只是简单的浅拷贝。 上面被注释掉的程序就是编译器自动添加的部分。 从而导致在sayHello中向参数x传递值时,调用了bitwise copy的拷贝构造函数,使得x对象和b对象中的值完全一致,包括p指针的值,在x离开作用域(也就是sayHello函数结束),x发生析构,调用delete 销毁了指针p,同时在main函数结束的时候,析构b时又会调用一次delete删除指针p。

    也就是本程序会delete一直已经被delete 的指针。可以做如下改进,来修复程序:
     
    class A{
       int i;
    };
    class B{
       A *p;
    public:
       B(){p=new A;}
       ~B(){delete p;}
       B(const B& other){
           p = new A;       //构建新的指针
           *p = *(other.p); //将指向的内容复制,依然指向不同的位置
       }
    };
    void sayHello(B b){
    }
    int main(){
       B b;
       sayHello(b);
    }
    

    如上,在B中添加copy 构造函数

    13.(不定项)在C++面向对象编程语言中,以下阐述不正确的是:

      A.接口中可以用虚方法

      B.一个类可以实现多个接口

      C.接口不能被实例化

      D.接口中可以包含已经实现的方法

    分析:答案:AD。

    所谓的接口是指只包含纯虚函数的抽象类,和普通的抽象类含不一样。所以A不对,必须是纯虚函数。然后B是正确的没有问题:接口的实现是通过子类的继承来实现的,可以有多个子类继承。然后是C,刚才说接口是特殊的抽象类,抽象类的唯一左右就是创建派生类,不能定义抽象类的对象,所以C是正确的。对于D,接口即只包含纯虚函数的抽象类,所以D是不对的。

    14、(不定项)下面关于HTTP协议的说法正确的是:

      A.HTTP是基于TCP协议之上的应用层协议

      B.HTTP是一个普通用在浏览器和web服务器之间进行数据交换的流式二进制协议

      C.HTTP协议的ETAG响应头主要用于信息的过期验证

      D.HTTP1.0中的cache-control响应头主要用于控制信息在浏览器的缓存

    分析:答案:AC。

    HTTP是文本协议,不是二进制协议,B是错的;cache-control是在HTTP1.1中才有的,D是错的。

    15、(不定项)关于多线程和多进程编程,下面描述正确的是():

      A.多进程里,子进程可获得父进程的所有堆和栈的数据;而线程会与同进程的其他线程共享数据,拥有自己的栈空间

      B.线程因为有自己的独立栈空间且共享数据,所有执行的开销相对较大,同时不利于资源管理和保护

      C.线程的通信速度更快,切换更快,因为他们在同一地址空间内

      D.线程使用公共变量/内存时需要使用同步机制,因为他们在同一地址空间内

      E.因多线程里,每个子进程有自己的地址空间,因此相互之间通信时,线程不如进程灵活和方便

    分析:答案:ACD。

    线程和进程的区别联系:

    1,进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。

    2,线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
    两者都可以提高程序的并发度,提高程序运行效率和响应时间。

    线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
    根本区别就一点:用多进程每个进程有自己的地址空间(address space),线程则共享地址空间。所有其它区别都是由此而来的:
    1、速度:线程产生的速度快,线程间的通讯快、切换快等,因为他们在同一个地址空间内。
    2、资源利用率:线程的资源利用率比较好也是因为他们在同一个地址空间内。
    3、同步问题:线程使用公共变量/内存时需要使用同步机制还是因为他们在同一个地址空间内
     
     
     
  • 相关阅读:
    c# Array.Sort() 对数组排列
    【软件配置】JDK+AndroidStudio4.1开发安卓APP环境安装和配置教程详细
    【QT】跨线程的信号槽(connect函数)
    【QT】QtConcurrent::run()+QThreadPool实现多线程
    【QT】继承QRunnable+QThreadPool实现多线程
    【QT】子类化QObject+moveToThread实现多线程
    【QT】子类化QThread实现多线程
    【QT】QThread源码浅析
    【C++】 C++异常捕捉和处理
    【QT】 Qt之QComboBox删除下拉item时出现段错误
  • 原文地址:https://www.cnblogs.com/carsonzhu/p/5212626.html
Copyright © 2011-2022 走看看