微软的100道算法面试题(终结版)

前言

数据结构与算法的重要性已不言而喻,最近,我整理出十大经典排序算法、五大常用算法总结,今天特意整理出微软面试的100题,若有不足之处,欢迎指正!由于篇幅过长,前30道题目写在上一篇,大家可以进我的个人主页浏览,之后我会抽时间争取把数据结构与算法做成一个系列,敬请期待!

微软的100道算法面试题(终结版)

31、和为n 连续正数序列

题目:输入一个正数n,输出所有和为n 连续正数序列。

例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3 个连续序列1-5、4-6 和7-8。

32、二元树的深度

题目:输入一棵二元树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

分析:这道题本质上还是考查二元树的遍历。

33、字符串的排列

题目:输入一个字符串,打印出该字符串中字符的所有排列。

例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串abc、acb、bac、bca、cab 和cba。

分析:这是一道很好的考查对递归理解的编程题。

34、调整数组顺序使奇数位于偶数前面

题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。要求时间复杂度为O(n)。

35、最长公共字串

题目:如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字符串二的子串。注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中。

请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串。

例如:输入两个字符串BDCABA 和ABCBDAB,字符串BCBA 和BDAB 都是是它们的最长公共子串,则输出它们的长度4,并打印任意一个子串。

分析:求最长公共子串是一道非常经典的动态规划题。

36、从尾到头输出链表

题目:输入一个链表的头结点,从尾到头反过来输出每个结点的值。

链表结点定义如下:

struct ListNode

{

int m_nKey;

ListNode* m_pNext;

};

37、在O(1)时间内删除链表结点

题目:给定链表的头指针和一个结点指针,在O(1)时间删除该结点。

链表结点的定义如下:

struct ListNode

{

int m_nKey;

ListNode* m_pNext;

};

void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted);

分析:这道题考察编程基本功和反应速度,更重要的是考察面试者对时间复杂度的理解。

38、找出数组中两个只出现一次的数字

题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

分析:这是一道很新颖的关于位运算的面试题。

39、找出链表的第一个公共结点

题目:两个单向链表,找出它们的第一个公共结点。

链表的结点定义为:

struct ListNode

{

int m_nKey;

ListNode* m_pNext;

};

分析:这是一道微软的面试题,在微软的面试题中,链表出现的概率相当高。

40、在字符串中删除特定的字符

题目:输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”, 则删除之后的第一个字符串变成”Thy r stdnts.”。

分析:在微软的常见面试题中,与字符串相关的题目占了很大的一部分,因为写程序操作字符串能很好的反映面试者的编程基本功。

41、 寻找丑数

题目:我们把只包含因子2、3 和5 的数称作丑数(Ugly Number)。例如6、8 都是丑数,但14 不是,因为它包含因子7。习惯上我们把1 当做是第一个丑数。求按从小到大的顺序的第1500 个丑数。

42、输出1 到最大的N 位数

题目:输入数字n,按顺序输出从1 最大的n 位10 进制数。比如输入3,则输出1、2、3 一直到最大的3 位数即999。

分析:这是一道很有意思的题目,看起来很简单,其实里面却有不少的玄机。

43、颠倒栈

题目:用递归颠倒一个栈。例如输入栈{1, 2, 3, 4, 5},1 在栈顶。颠倒之后的栈为{5, 4, 3, 2, 1},5 处在栈顶。

44、闲玩娱乐

(1)扑克牌的顺子

从扑克牌中随机抽5 张牌,判断是不是一个顺子,即这5 张牌是不是连续的。2-10 为数字本身,A 为1,J 为11,Q 为12,K 为13,而大小王可以看成任意数字。

(2)n 个骰子的点数。把n 个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,

打印出S 的所有可能的值出现的概率。

45、把数组排成最小的数

题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的

一个。例如输入数组{32, 321},则输出这两个能排成的最小数字32132。

请给出解决问题的算法,并证明该算法。

分析:这是百度的一道面试题,从这道题我们可以看出百度对应聘者在算法方面有很高的要求。

46、旋转数组中的最小元素

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个

排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。

分析:这道题最直观的解法并不难,我们应该利用输入数组的特性找到更好的解法。

47、数值的整数次方

题目:实现函数double Power(double base, int exponent),求base 的exponent 次方。

不需要考虑溢出。

48、 题目:设计一个类,我们只能生成该类的一个实例。

分析:只能生成一个实例的类是实现了Singleton 模式的类型。

49、对策字符串的最大长度

题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。

分析:可能很多人都写过判断一个字符串是不是对称的函数,这个题目可以看成是该函数的

加强版。

50、数组中超过出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。

分析:这道面试题百度、微软和Google 在内的多家公司都采用过,解答这道题除了较好的编程能力外,还需要较快的反应和较强的逻辑思维能力。

51、二叉树两个结点的最低共同父结点

题目:二叉树的结点定义如下:

struct TreeNode

{

int m_nvalue;

TreeNode* m_pLeft;

TreeNode* m_pRight;

};

输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。

52、复杂链表的复制

题目:有一个复杂链表,其结点除了有一个m_pNext 指针指向下一个结点外,还有一个m_pSibling 指向链表中的任一结点或者NULL。其结点的C++定义如下:

struct ComplexNode

{

int m_nValue;

ComplexNode* m_pNext;

ComplexNode* m_pSibling;

};

下图是一个含有5 个结点的该类型复杂链表。

微软的100道算法面试题(终结版)

图中实线箭头表示m_pNext 指针,虚线箭头表示m_pSibling 指针。为简单起见,指向NULL 的指针没有画出。请完成函数ComplexNode* Clone(ComplexNode* pHead),以复制一个复杂链表。

53、关于链表问题的面试题目如下:

(1)给定单链表,检测是否有环。

使用两个指针p1,p2 从链表头开始遍历,p1 每次前进一步,p2 每次前进两步。如果p2 到达链表尾部,说明无环,否则p1、p2 必然会在某个时刻相遇(p1==p2),从而检测到链表中有环。

(2)给定两个单链表(head1, head2),检测两个链表是否有交点,如果有返回第一个交点。如果head1==head2,那么显然相交,直接返回head1。否则,分别从head1,head2 开始遍历两个链表获得其长度len1 与len2,假设len1>=len2,那么指针p1 由head1 开始向后移动len1-len2 步,指针p2=head2,下面p1、p2 每次向后前进一步并比较p1p2 是否相等,如果相等即返回该结点,否则说明两个链表没有交点。

(3)给定单链表(head),如果有环的话请返回从头结点进入环的第一个节点。

运用题一,我们可以检查链表中是否有环。如果有环,那么p1p2 重合点p 必然在环中。从p 点断开环,方法为:p1=p, p2=p->next, p->next=NULL。此时,原单链表可以看作两条单链表,一条从head 开始,另一条从p2 开始,于是运用题二的方法,我们找到它们的第一个交点即为所求。

(4)只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。办法很简单,首先是放p 中数据,然后将p->next 的数据copy 入p 中,接下来删除p->next即可。

(5)只给定单链表中某个结点p(非空结点),在p 前面插入一个结点。办法与前者类似,首先分配一个结点q,将q 插入在p 后,接下来将p 中的数据copy 入q中,然后再将要插入的数据记录在p 中。

54、链表和数组的区别在哪里?

分析:主要在基本概念上的理解,但是最好能考虑的全面一点。

55、(1)编写实现链表排序的一种算法。说明为什么你会选择用这样的方法?

(2)编写实现数组排序的一种算法。说明为什么你会选择用这样的方法?

(3)请编写能直接实现strstr()函数功能的代码。

56、阿里巴巴一道笔试题

题目:12 个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?

(1)一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

(2)一个文件,内含一千万行字符串,每个字符串在1K 以内,要求找出所有相反的串对,如abc 和cba。

(3)STL 的set 用什么实现的?为什么不用hash?

题目:给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数。

要求:空间复杂度O(1),时间复杂度为O(n)。

59、用C 语言实现函数void * memmove(void *dest, const void *src, size_t n)。memmove 函数的功能是拷贝src 所指的内存内容前n 个字节到dest 所指的地址上。

分析:由于可以把任何类型的指针赋给void 类型的指针, 这个函数主要是实现各种数据类型的拷贝。

60、又见字符串的问题

(1)给出一个函数来复制两个字符串A 和B。字符串A 的后几个字节和字符串B 的前几个字节重叠。分析:记住,这种题目往往就是考你对边界的考虑情况。

(2)已知一个字符串,比如asderwsde,寻找其中的一个子字符串比如sde 的个数,如果没有返回0,有的话返回子字符串的个数。

61、怎样编写一个程序,把一个有序整数数组放到二叉树中?

分析:本题考察二叉搜索树的建树方法,简单的递归结构。关于树的算法设计一定要联想到递归,因为树本身就是递归的定义。

62、(1)大整数数相乘的问题。

(2)求最大连续递增数字串(如“ads3sl456789DF3456ld345AA”中的“456789”)

(3)实现strstr 功能,即在父串中寻找子串首次出现的位置。

63、金山笔试题,编码完成下面的处理函数。

题目:函数将字符串中的字符'*'移到串的前部分,前面的非'*'字符后移,但不能改变非'*'字符的先后顺序,函数返回串中字符'*'的数量。如原始串为:ab**cd**e*12,处理后为*****abcde12,函数并返回值为5。(要求使用尽量少的时间和辅助空间)

64、神州数码、华为笔试题

(1)华为软件研发笔试题,实现一单链表的逆转。

(2)编码实现字符串转整型的函数(实现函数atoi 的功能),据说是神州数码笔试题。如将字符串”+123”123, ”-0123”-123, “123CS45”123, “123.45CS”123, “CS123.45”0

(3)快速排序

(4)删除字符串中的数字并压缩字符串。如字符串”abc123de4fg56”处理后变为”abcdefg”。注意空间和效率。

(5)求两个串中的第一个最长子串。

如"abractyeyt","dgdsaeactyey"的最大子串为"actyet"。

65、(1)不开辟用于交换数据的临时空间,如何完成字符串的逆序

(2)删除串中指定的字符

(3)判断单链表中是否存在环。

66、一道著名的毒酒问题

有1000 桶酒,其中1 桶有毒。而一旦吃了,毒性会在1 周后发作。现在我们用小老鼠做实验,要在1 周内找出那桶毒酒,问最少需要多少老鼠。

67、有趣的石头问题

有一堆1 万个石头和1 万个木头,对于每个石头都有1 个木头和它重量一样,把配对的石头和木头找出来。

68、在一个int 数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数。直观想法是用两个数组a、b。a[i]、b[i]分别保存从前到i 的最大的数和从后到i 的最小的数,一个解答。

69、微软笔试题

求随机数构成的数组中找到长度大于=3 的最长的等差数列, 输出等差数列由小到大,如果没有符合条件的就输出格式:

输入[1,3,0,5,-1,6]

输出[-1,1,3,5]

要求时间复杂度,空间复杂度尽量小。

70、华为面试题

(1)判断一字符串是不是对称的,如:abccba。

(2)用递归的方法判断整数组a[N]是不是升序排列。

最后压轴之戏,终结微软公司的面试题:

第1 组微软较简单的算法面试题

1、编写反转字符串的程序,要求优化速度、优化空间。

2、在链表里如何发现循环链接?

3、编写反转字符串的程序,要求优化速度、优化空间。

4、给出洗牌的一个算法,并将洗好的牌存储在一个整形数组里。

5、写一个函数,检查字符是否是整数,如果是,返回其整数值。

(或者:怎样只用4 行代码编写出一个从字符串到长整形的函数?)

第2 组微软面试题

1、给出一个函数来输出一个字符串的所有排列。

2、请编写实现malloc()内存分配函数功能一样的代码。

3、给出一个函数来复制两个字符串A 和B。字符串A 的后几个字节和字符串B 的前几个字节重叠。

4、怎样编写一个程序,把一个有序整数数组放到二叉树中?

5、怎样从顶部开始逐层打印二叉树结点数据?请编程。

6、怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?

第3 组微软面试题

1、烧一根不均匀的绳,从头烧到尾总共需要1 个小时。现在有若干条材质相同的绳子,问如何用烧绳的方法来计时一个小时十五分钟呢?

2、你有一桶果冻,其中有黄色、绿色、红色三种,闭上眼睛抓取同种颜色的两个。抓取多少个就可以确定你肯定有两个同一颜色的果冻?(5 秒-1 分钟完成)

3、如果你有无穷多的水,一个3 公升的提捅,一个5 公升的提捅,两只提捅形状上下都不均

匀,问你如何才能准确称出4 公升的水?(40 秒-3 分钟完成)

第4 组微软面试题,挑战思维极限

1、12 个球一个天平,现知道只有一个和其它的重量不同,问怎样称才能用三次就找到那个

球。13 个呢?(注意此题并未说明那个球的重量是轻是重,所以需要仔细考虑)(5 分钟-1 小时完成)

2、在9 个点上画10 条直线,要求每条直线上至少有三个点?(3 分钟-20 分钟完成)

3、在一天的24 小时之中,时钟的时针、分针和秒针完全重合在一起的时候有几次?都分别是什么时间?你怎样算出来的?(5 分钟-15 分钟完成)

最后

为了让学习变得轻松高效, 现在给大家提供一个学习平台,让你在实践中积累经验掌握原理。主要方向是JAVA架构师,在这里你可以学习Java工程化、高性能及分布式、深入浅出、性能调优、Spring,MyBatis,Netty源码分析和大数据等知识点,免费的大型互联网Java技术视频分享给大家。

微软的100道算法面试题(终结版)

后台私信回复“架构” 即可免费获得这套价值一万六的内部教材!


分享到:


相關文章: