腾讯、百度、阿里、微软面试题精选(不断更新)

1、for(i=0;i<10;++i,sum+=i);  循环结束时 i 和sum的值分别是多少?
  分析:循环结束时 i=10应该没有问题,sum计算的位置不是很常见,每次sum+=i 时,i 的值都是先自加1,即 i(从0到9),计算sum时是从1加到10,结果55;
如果是:for(i=0;i<10;++i)  sum+=i;  循环结束时 i 和sum的值分别是多少?
  这次 i 依然是10,但是sum就是0到9的加和,结果45。

2、请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句。
  #define Max(a,b) ((a-b)&(0x80))? b:a
  #define Max(a,b) ((a-b)&(1<<31))? b:a  两种写法是等价的。
注意:#define Max(a,b) (a/b)?a:b  这个答案是不全面的,只适用于正整数。

3、不使用额外空间,将 A,B两链表的元素交叉归并。
  代码使用了递归的方式实现合并两个链表:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 typedef struct node
 5 {
 6     int val;
 7     struct node *next;
 8 }node;
 9 
10 node* createList(int n)
11 {
12     node *head;
13     node *pHead;//永远指向最新的节点
14     node *pNext;//指向新添加的节点
15     for(int i=0;i<n;i++)
16     {
17         if(i==0)
18         {
19             head=new node;
20             cout<<"请输入第1个元素(头结点)的值:";
21             cin>>head->val;
22             head->next=NULL;
23             pHead=head;
24         }
25         else
26         {
27             pNext=new node;
28             cout<<"请输入第"<<i+1<<"个元素的值:";
29             cin>>pNext->val;
30             pNext->next=NULL;
31             pHead->next=pNext;
32             pHead=pNext;
33         }
34     }
35     return head;
36 }
37 
38 void mergeTwoList(node *headA,node *headB)//headA的长度大于等于headB的
39 {
40     if(headA==NULL||headB==NULL)
41     {
42         return;
43     }
44     mergeTwoList(headA->next,headB->next);//递归实现
45     headB->next=headA->next;
46     headA->next=headB;
47 }
48 
49 int main()
50 {
51     node *headA;
52     node *headB;
53     node *newList;
54     cout<<"新建链表A:\n";
55     headA=createList(5);
56     cout<<"新建链表B:\n";
57     headB=createList(3);
58     newList=headA;
59     mergeTwoList(headA,headB);
60     cout<<"合并后的新链表:"<<endl;
61     while(newList!=NULL)
62     {
63         cout<<newList->val<<" ";
64         newList=newList->next;
65     }
66     return 0;
67 }

4、*p=NULL *p=new char[100]  sizeof(p)各为多少?(一般都指的32位计算机)只要是指针变量都是4字节的,也就是计算机寻址空间是0到(2^32-1),即32位。

5、C语言中的内存泄漏:

动态内存的意思是程序运行时在堆上申请的内存。
而静态内存是程序编译时,在静态存储区申请的内存。
动态内存泄露指的是程序运行时,使用的new malloc realloc等函数没有与之匹配的delete free等函数。
造成程序不断的同操作系统申请内存,而又不还给操作系统,申请的多了,操作系统本身也就没内存可用了。
而应用程序,一旦退出,那么操作系统是会自动回收该应用程序所在进程的全部资源的,所以,泄露的内存也就会被操作系统全部回收。

应用程序的内存分为四块:堆区,栈区,全局数据区,代码区  
其中堆区需要程序员自己管理,我们申请的动态变量就存放在堆区,用完后需要程序员自己手动释放。
若申请了一块动态内存,未释放,却丢失了指向性,这就叫内存泄露,会导致程序的可用内存减少,严重的话会拖垮操作系统。

6、

32位机上根据下面的代码,问哪些说法是正确的?()

    signed char a = 0xe0;
    unsigned int b = a;
    unsigned char c = a;

    A. a>0 && c>0 为真 
    B. a == c 为真 
    C. b 的十六进制表示是:0xffffffe0 
    D.上面都不对

有符号数和无符号数之间的转换:c
首先,a=1110 0000,首位是1,signed是有符号数,所以是负的;unsigned int 是4个字节的,无符号数,把a转换成b时,负数前面补1,正数补0,所以b的16进制表示0xffffffe0;
  c是无符号数,单字节的,c=0xe0,是正数。

转一篇很好的博客,看了就懂了:

#include <stdio.h>
int main(int argc, char *argv[])
{
unsigned char a = -1;
char b = a;
printf("%d %d",a,b);

return 0;
}
//结果:255  -1
复制代码
复制代码
#include <stdio.h>
int main(int argc, char *argv[])
{
unsigned short a = -1;
short b = a;
printf("%d %d",a,b);

return 0;
}
//结果:65535 -1
复制代码

这是两段很简单的代码,我就以第二段代码为例。

     在计算机中,负数是以补码来存储的。  转载请注明出处http://www.cnblogs.com/stonehat/archive/2011/10/14/2212141.html

      C语言中常量整数 -1的补码表示为0xFFFFFFFF。截取后面16位FFFF赋值给 变量a(unsigned short)。此时 a = 0xFFFF(a没有符号位,0xFFFF转换为十进制为65535)

      a又将0xFFFF,直接赋值给short b。 此时 b = 0xFFFF(但是要注意,b是有符号的,0xFFFF转换为十进制为-1)

执行printf("%d %d",a,b);的时候,要将 a和b的值先转换为int型:(这里是重点!!!)

 a没有符号所以转为int型为0x0000FFFF,

 b有符号转换为int型为0xFFFFFFFF。

十进制输出值 65535  -1.   转载请注明出处http://www.cnblogs.com/stonehat/archive/2011/10/14/2212141.html

复制代码
#include <stdio.h>
int main(int argc, char *argv[])
{

unsigned int a = -1;
int b = a;
printf("%d %d",a,b);

return 0;
}
//结果 -1 -1
复制代码

转载请注明出处http://www.cnblogs.com/stonehat/archive/2011/10/14/2212141.html
a在内存中值为0xFFFFFFFF,b的值为0xFFFFFFFF,都已经32位,

a转换为int型的时候就是0xFFFFFFFF,所以输出-1.

其实,记住两点就行了

1.unsigned 类型转换为 signed类型的时候是直接复制到低位,高位为0.如果signed类型位数不够,只直接装载unsigned低位。

2.signed类型转换为unsigned类型的时候,也是将补码直接复制到低位,高位为符号位。如果unsigned位数不够,只直接装载signed低位。

7、

 1 下面哪些选项能编译通过 2 int i;
 3 char a[10]; 
 4 string f(); 
 5 string g(string &str);  
 6 
 7 A. if(!!i){f();} 
 8 B. g(f()); 
 9 C. a=a+1; 
10 D. g("abc"); 

解析:c、c++会给未初始化的变量随机赋值,所以A是可以的;B是错误的,因为一个函数的返回值是一个临时变量,g函数参数是一个引用变量,应该传入一个定义好的变量作为参数,例如 string a="abc";g(a);所以D也是错误的,如果是g(string str)函数,B、D都是对的。C是错的,因为a是指向数组a[10]的首地址的指针,是个常量,不能赋值的,就像5=5+1是不可能的。但是 char *p; p=a;p++;这就可以了,因为p是变量了。

8、

问下面的数据都存放在哪些存储区?

int main()
{
    char *p = "hello,world";
    return 0;
}

A. 堆和静态数据区
B. 栈和静态数据区
C. 栈和常量区
D. 栈和堆

解析:根据C语言中的特性和定义p是一个局部变量,而C语言中局部变量存在于栈中,"hello wrold"是一个字符串常量,因此存储于程序的只读存储区中,p在这里其实只是指向了"hello wrold"在只读存储区中的地址而已。

12、问题:在一个二维数组中,每行的元素从左到右是递增的,每列元素从上到下是递增的。写一个函数,查找一给定的元素是否在此数组中

输入:一个二维数组,和一个待查找的数

输出:待查找的数在数组中输出“YES",否则输出”NO"

原始思路:最简单思路就是暴力搜索,遍历一遍数组中的元素时间复杂度为O(n2)。但是这样就没有用问题的已知条件(从左到右、从上到下递增),因此不是个好的解法

改进1:从第一行开始找,找到待查元素大的,如果还没找到,接着从第二行开始找,直到找到或到最后一个元素为止(如图),但是如果带查找的元素在最后,还得遍历到最后,时间复杂度还是O(n2)

        

改进2:上来在随机在里面挑一个,如果正好逮住,那就结束了;如果比待查找的元素大,那么他的左边和上边;否则在右边和下边。如下图。这样下来可以减少一部分元素的比较。在寻找1时,会话费反而很多时间,并不是个好的解决办法。

           

改进3:看两个比较关键的两个点——左下角和右上角。以右上角为例(如下图)。如果右上角元素等于带查找元素,那就返回真;如果右上角元素大于待查找元素,那就删除右上角元素所在列;否则删除其所在行。依次进行下去。

                  

举例说明
      

参考代码一

 
#include <stdio.h>

int find_value(int a[][4], int value, int x, int y)//(x,y)表示右上角坐标
{
    if ((x >= 0) && (y < 4))
    {
        if (a[x][y] ==  value)
            return 1;
        else if (a[x][y] > value)
            return find_value(a, value, x-1, y);
        else
            return find_value(a, value, x, y+1);
    }

    return 0;
}

int main()
{
    int a[4][4] = {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
    int val;
    printf("Enter your number:");
    scanf("%d", &val);
    if(find_value(a, val, 3, 0))
        printf("Yes, find it\n");
    else
        printf("No, not find it\n");

    return 0;
}
原文地址:https://www.cnblogs.com/nannanITeye/p/3005999.html