各大计算机公司 笔试及面试 题目 - 微软(一)

备注: 转至 周磊的博客,http://blog.csdn.net/v_JULY_v/article/details/6234496


1、有一个整数数组,请求出两两之差绝对值最小的值,

记住,只要得出最小值即可,不需要求出是哪两个数。


2、一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}
是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数。


3、微软亚院之编程判断俩个链表是否相交

给出俩个单向链表的头指针,比如h1,h2,判断这俩个链表是否相交。
为了简化问题,我们假设俩个链表均不带环。

问题扩展:
1.如果链表可能有环列?
2.如果需要求出俩个链表相交的第一个节点列?



8、请编写能直接实现int atoi(const char * pstr)函数功能的代码。

9、编程实现两个正整数的除法
编程实现两个正整数的除法,当然不能用除法操作符。
// return x/y.
int div(const int x, const int y) 
{
  ....
}

10、在排序数组中,找出给定数字的出现次数
比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。

11、平面上N个点,每两个点都确定一条直线,
求出斜率最大的那条直线所通过的两个点(斜率不存在的情况不考虑)。时间效率越高越好。

12、一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
注意:
- 5个数值允许是乱序的。比如: 8 7 5 0 6
- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
- 0可以多次出现。
- 复杂度如果是O(n2)则不得分。

13、设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
复杂度如果是O(n2)则不得分。

14、一棵排序二叉树,令 f=(最大值+最小值)/2,
设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是O(n2)则不得分。

15、一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。
设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
复杂度最好是O(n),如果是O(n2)则不得分。

16、微软面试题
一个有序数列,序列中的每一个值都能够被2或者3或者5所整除,1是这个序列的第一个元素。求第1500个值是多少?


17、请把一个整形数组中重复的数字去掉。例如: 
1,   2,   0,   2,   -1,   999,   3,   999,   88 
答案应该是: 
1,   2,   0,   -1,   999,   3,   88




62、微软三道面试题
yeardoublehua
1. 给一个有N个整数的数组S..和另一个整数X,判断S里有没有2个数的和为X,
请设计成O(n*log2(n))的算法。
2. 有2个数组..里面有N个整数。
设计一个算法O(n log2(n)),看是否两个数组里存在一个同样的数。
3. 让你排序N个比N^7小的数,要求的算法是O(n)(给了提示..说往N进制那方面想)

qq120848369:
1,快排,头尾夹逼.

  1. #include <iostream>  
  2. #include <algorithm>  
  3. #include <utility>  
  4. using namespace std;  
  5. typedef pair<int,int> Pair;  
  6.   
  7. Pair findSum(int *s,int n,int x)  
  8. {  
  9.     sort(s,s+n);   //引用了库函数  
  10.   
  11.     int *begin=s;  
  12.     int *end=s+n-1;  
  13.   
  14.     while(begin<end)    //俩头夹逼,很经典的方法  
  15.     {  
  16.         if(*begin+*end>x)  
  17.         {  
  18.             --end;  
  19.         }  
  20.         else if(*begin+*end<x)  
  21.         {  
  22.             ++begin;  
  23.         }  
  24.         else  
  25.         {  
  26.             return Pair(*begin,*end);  
  27.         }  
  28.     }  
  29.   
  30.     return Pair(-1,-1);  
  31. }  
  32.   
  33. int main()  
  34. {    
  35.     int arr[100]=  
  36.     {  
  37.         3, -4, 7, 8, 12, -5, 0, 9  
  38.     };  
  39.       
  40.     int n=8,x;  
  41.   
  42.     while(cin>>x)  
  43.     {  
  44.         Pair ret=findSum(arr,n,x);  
  45.         cout<<ret.first<<","<<ret.second<<endl;  
  46.     }  
  47.   
  48.     return 0;  
  49. }  

2,快排,线性扫描

  1. #include <iostream>  
  2. #include <algorithm>  
  3. using namespace std;  
  4.   
  5. bool findSame(const int *a,int len1,const int *b,int len2,int *result)  
  6. {  
  7.     int i,j;  
  8.     i=j=0;  
  9.   
  10.     while(i<len1 && j<len2)  
  11.     {  
  12.         if(a[i]<b[j])  
  13.         {  
  14.             ++i;  
  15.         }  
  16.         else if(a[i]>b[j])  
  17.         {  
  18.             ++j;  
  19.         }  
  20.         else  
  21.         {  
  22.             *result=a[i];  
  23.             return true;  
  24.         }  
  25.     }  
  26.     return false;  
  27. }  
  28.   
  29. int main()  
  30. {  
  31.     int a[100],b[100],len1,len2,result;  
  32.     cin>>len1;  
  33.   
  34.     for(int i=0;i<len1;++i)  
  35.     {  
  36.         cin>>a[i];  
  37.     }  
  38.   
  39.     cin>>len2;  
  40.     for(int i=0;i<len2;++i)  
  41.     {  
  42.         cin>>b[i];  
  43.     }  
  44.   
  45.     if( findSame(a,len1,b,len2,&result) )  
  46.     {  
  47.         cout<<result<<endl;  
  48.     }  
  49.     return 0;  
  50. }  

3,基数排序已经可以O(n)了,准备10个vector<int>,从最低位数字开始,放入相应的桶里,然后再顺序取出来,然后再从次低位放入相应桶里,在顺序取出来.比如:N=5,分别是:4,10,7,123,33
0 :10


3 :123,33
4 :4


7 :7

9

顺次取出来:10,123,33,,4,7
0 :4,7
1 :10
2 :123
3 :33





9

依次取出来:4,7,10,123,33
0 :4,7,10,33
1 :123







9

依次取出来:4,7,10,33,123
完毕。
代码,如下:

  1. #include <iostream>  
  2. #include <string>  
  3. #include <queue>  
  4. #include <vector>  
  5.   
  6. using namespace std;  
  7.   
  8. size_t n;    //n个数  
  9. size_t maxLen=0;    //最大的数字位数  
  10. vector< queue<string> > vec(10);    //10个桶  
  11. vector<string> result;  
  12.   
  13. void sort()  
  14. {  
  15.     for(size_t i=0;i<maxLen;++i)  
  16.     {  
  17.         for(size_t j=0;j<result.size();++j)  
  18.         {  
  19.             if( i>=result[j].length() )  
  20.             {  
  21.                 vec[0].push(result[j]);  
  22.             }  
  23.             else  
  24.             {  
  25.                 vec[ result[j][result[j].length()-1-i]-'0' ].push(result[j]);  
  26.             }  
  27.         }  
  28.   
  29.         result.clear();  
  30.   
  31.         for(size_t k=0;k<vec.size();++k)  
  32.         {  
  33.             while(!vec[k].empty())  
  34.             {  
  35.                 result.push_back(vec[k].front());  
  36.                 vec[k].pop();  
  37.             }  
  38.         }  
  39.     }  
  40. }  
  41.   
  42. int main()  
  43. {  
  44.     cin>>n;  
  45.       
  46.     string input;  
  47.   
  48.     for(size_t i=0;i<n;++i)  
  49.     {  
  50.         cin>>input;  
  51.         result.push_back(input);  
  52.   
  53.         if(maxLen == 0 || input.length()>maxLen)  
  54.         {  
  55.             maxLen=input.length();  
  56.         }  
  57.     }  
  58.   
  59.     sort();  
  60.   
  61.     for(size_t i=0;i<n;++i)  
  62.     {  
  63.         cout<<result[i]<<"  ";  
  64.     }  
  65.   
  66.     cout<<endl;  
  67.   
  68.     return 0;  
  69. }  

xiaoboalex:
第一题,1. 给一个有N个整数的数组S..和另一个整数X,判断S里有没有2个数的和为X,
请设计成O(n*log2(n))的算法。

如果限定最坏复杂度nlgn的话就不能用快排。
可以用归并排序,然后Y=X-E,用两分搜索依次查找每一个Y是否存在,保证最坏复杂度为nlgn.


63、微软亚洲研究院
hinyunsin
假设有一颗二叉树,已知这棵树的节点上不均匀的分布了若干石头,石头数跟这棵二叉树的节点数相同,石头只可以在子节点和父节点之间进行搬运,每次只能搬运一颗石头。请问如何以最少的步骤将石头搬运均匀,使得每个节点上的石头上刚好为1。

个人,暂时还没看到清晰的,更好的思路,以下是网友mathe、casahama、Torey等人给的思路:
mathe:
我们对于任意一个节点,可以查看其本身和左子树,右子树的几个信息:
i)本身上面石子数目
ii)左子树中石子数目和节点数目的差值
iii)右子树中石子数目和节点数目的差值
iv)通过i),ii),iii)可以计算出除掉这三部份其余节点中石子和节点数目的差值。
如果上面信息都已经计算出来,那么对于这个节点,我们就可以计算出同其关联三条边石子运送最小数目。比如,如果左子树石子数目和节点数目差值为a<0,那么表示比如通过这个节点通向左之数的边至少运送a个石子;反之如果a>0,那么表示必须通过这个节点通向左子树的边反向运送a个石子。同样可以计算出同父节点之间的最小运送数目。
然后对所有节点,将这些数目(ii,iii,iv中)绝对值相加就可以得出下界。
而证明这个下界可以达到也很简单。每次找出一个石子数目大于1的点,那么它至少有一条边需要向外运送,操作之即可。每次操作以后,必然上面这些绝对值数目和减1。所以有限步操作后必然达到均衡。所以现在唯一余下的问题就是如何计算这些数值问题。这个我们只要按照拓扑排序,从叶节点开始向根节点计算即可。

casahama:
节点上的石头数不能小于0。所以当子节点石头数==0 并且 父节点石头数==0的时候,是需要继续向上回溯的。基于这一点,想在一次遍历中解决这个问题是不可能的。
这一点考虑进去的话,看来应该再多加一个栈保存这样类似的结点才行.

Torey:
后序遍历
证明:
在一棵只有三个节点的子二叉树里,石头在子树里搬运的步数肯定小于等于子树外面节点搬运的步数。
石头由一个子树移到另一个子数可归结为两步,一为石头移到父节点,二为石头由父节点移到子树结点,所以无论哪颗石头移到哪个节点,总步数总是一定。

关于树的遍历,在面试题中已出现过太多次了,特此稍稍整理以下:
二叉树结点存储的数据结构:
typedef char datatype;
typedef struct node
 {
   datatype data;
   struct node* lchild,*rchild;
 } bintnode;

typedef bintnode* bintree;
bintree root;

1.树的前序遍历即:
按根 左 右 的顺序,依次
前序遍历根结点->前序遍历左子树->前序遍历右子树

前序遍历,递归算法
void preorder(bintree t)    
 //注,bintree为一指向二叉树根结点的指针
{
   if(t)
    {
      printf("%c",t->data);
      preorder(t->lchild);
      preorder(t->rchild);
    }
}

2.中序遍历,递归算法
void preorder(bintree t)
{
   if(t)
    {

      inorder(t->lchild);
      printf("%c",t->data);
      inorder(t->rchild);
    }
}

3.后序遍历,递归算法
void preorder(bintree t)
{
   if(t)
    {

      postorder(t->lchild);
      postorder(t->rchild);
      printf("%c",t->data);
    }
}

关于实现二叉树的前序、中序、后序遍历的递归与非递归实现,的更多,请参考这(微软100题第43题答案):
http://blog.csdn.net/v_JULY_v/archive/2011/02/01/6171539.aspx





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值