微软等数据结构+算法面试100题(48)-- 微软十五道面试题

来源:互联网 发布:网络销售渠道有哪两种 编辑:程序博客网 时间:2024/06/11 19:45
微软十五道面试题


1、有一个整数数组,请求出两两之差绝对值最小的值,
记住,只要得出最小值即可,不需要求出是哪两个数。


2、写一个函数,检查字符是否是整数,如果是,返回其整数值。
(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)


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


4、(a)请编写实现malloc()内存分配函数功能一样的代码。 
(b)给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。


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


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


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


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)则不得分。



/*1、有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数。思路:先排序。排序后两两之差绝对值最小的值肯定是相邻元素的差的绝对值。这样时间复杂度是nlogn。*/


/*2、写一个函数,检查字符是否是整数,如果是,返回其整数值。(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)*/

/*15、一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。复杂度最好是O(n),如果是O(n2)则不得分。思路:首相对数列排序,排序复杂度为nlogn。排序后设俩个下标分别指向最小和最大的low,high。如果p[low]+p[high]==n+1,找到。如果p[low]+p[high]>n+1,high--。如果p[low]+p[high]<n+1,low++。当low>high的时候即可退出。*/

/*14、一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。复杂度如果是O(n2)则不得分。'思路:对于一个二叉排序树而言。最大最小值分别是最左和最右子节点的值。这样可以计算出f的值。复杂度是logn。然后就是从根节点开始遍历一遍二叉排序树。如果root->data==f;root=root->right;如果root->data>f;root=root->left;node=root;如果root->data<f;root=root->right;最后返回node值即可。*/

/*13、设计一个算法,找出二叉树上任意两个结点的最近共同父结点。复杂度如果是O(n2)则不得分。思路:首先找到从根节点到俩个节点的俩条路径。找到路径后就是比较俩条路劲。找到最后一个相等的节点。*/

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

/*11、平面上N个点,每两个点都确定一条直线,求出斜率最大的那条直线所通过的两个点(斜率不存在的情况不考虑)。时间效率越高越好。思路:首先按照横坐标排序。因为俩个横坐标离得越近斜率越大。排序后就计算相邻俩点的斜率。求最大的。*/

/*10、在排序数组中,找出给定数字的出现次数比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。思路:如果一个一个比较。复杂度是n。考虑到已经排好序了。所以可以采用二分搜索的思路。求出给定数字的lowbound和upperbound。这样upperbound-lowbound就是给定数字出现的次数。而计算lowbound和upperbound复杂度都是logn。所以最后时间复杂度也是logn。这样比逐个比较复杂度低。*/int LowBound(int *p,int low,int high,int n){while(low<high){int mid=low+(high-low)/2;if(p[mid]>=n)high=mid;elselow=mid+1;}return low;}int UpperBound(int *p,int low,int high,int n){while(low<high){int mid=low+(high-low)/2;if(p[mid]>n)high=mid;elselow=mid+1;}return low;}

/*9、编程实现两个正整数的除法编程实现两个正整数的除法,当然不能用除法操作符。// return x/y.int div(const int x, const int y) {  ....}这个题说白了就是在1到x之间找到一个数res。使得res*y<x但是(res+1)*y>x。思路1:就是从1开始一直到x这样的比较。思路2:既然是从1到x,其实也是可以用二分的思路。*/int Div(const int x, const int y) {   int res=-1;   for(int i=1;i<=x;i++)   {   if(i*y<x)   res=i;   }   return res;}int Div1(const int x, const int y) {int low=1,high=x;while(low<high){int mid=low+((high-low)>>1);int tmp=x-mid*y;if(tmp>=y)low=mid;if(tmp<0)high=mid;}}

// MS.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"using namespace std;typedef vector<int>::iterator Iter;//单链表节点struct ListNode{int data;ListNode* next;ListNode(int value=0,ListNode *pnext=NULL):data(value),next(pnext){}};//二叉树节点struct TreeNode{int data;TreeNode *left;TreeNode *right;TreeNode(int value=0,TreeNode *pleft=NULL,TreeNode *pright=NULL):data(value),left(pleft),right(pright){}};void ShowArray(int *p,int len){for(int i=0;i<len;i++)cout<<p[i]<<" ";cout<<endl;}void MidOrderTraverse(TreeNode* root){if(root==NULL)return;MidOrderTraverse(root->left);cout<<root->data<<" ";MidOrderTraverse(root->right);}/*微软十五道面试题1、有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数。2、写一个函数,检查字符是否是整数,如果是,返回其整数值。(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)3、给出一个函数来输出一个字符串的所有排列。4、(a)请编写实现malloc()内存分配函数功能一样的代码。 (b)给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。5、怎样编写一个程序,把一个有序整数数组放到二叉树中?6、怎样从顶部开始逐层打印二叉树结点数据?请编程。  7、怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?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)则不得分。*//*15、一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。复杂度最好是O(n),如果是O(n2)则不得分。思路:首相对数列排序,排序复杂度为nlogn。排序后设俩个下标分别指向最小和最大的low,high。如果p[low]+p[high]==n+1,找到。如果p[low]+p[high]>n+1,high--。如果p[low]+p[high]<n+1,low++。当low>high的时候即可退出。*//*14、一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。复杂度如果是O(n2)则不得分。'思路:对于一个二叉排序树而言。最大最小值分别是最左和最右子节点的值。这样可以计算出f的值。复杂度是logn。然后就是从根节点开始遍历一遍二叉排序树。如果root->data==f;root=root->right;如果root->data>f;root=root->left;node=root;如果root->data<f;root=root->right;最后返回node值即可。*//*13、设计一个算法,找出二叉树上任意两个结点的最近共同父结点。复杂度如果是O(n2)则不得分。思路:首先找到从根节点到俩个节点的俩条路径。找到路径后就是比较俩条路劲。找到最后一个相等的节点。*//*12、一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。注意:- 5个数值允许是乱序的。比如: 8 7 5 0 6- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4- 0可以多次出现。- 复杂度如果是O(n2)则不得分。思路:除过0最大最小分别是max和min。max-min+1应该要<=5。这样才能连续相邻。*//*11、平面上N个点,每两个点都确定一条直线,求出斜率最大的那条直线所通过的两个点(斜率不存在的情况不考虑)。时间效率越高越好。思路:首先按照横坐标排序。因为俩个横坐标离得越近斜率越大。排序后就计算相邻俩点的斜率。求最大的。*//*10、在排序数组中,找出给定数字的出现次数比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。思路:如果一个一个比较。复杂度是n。考虑到已经排好序了。所以可以采用二分搜索的思路。求出给定数字的lowbound和upperbound。这样upperbound-lowbound就是给定数字出现的次数。而计算lowbound和upperbound复杂度都是logn。所以最后时间复杂度也是logn。这样比逐个比较复杂度低。*//*1、有一个整数数组,请求出两两之差绝对值最小的值,记住,只要得出最小值即可,不需要求出是哪两个数。思路:先排序。排序后两两之差绝对值最小的值肯定是相邻元素的差的绝对值。这样时间复杂度是nlogn。*/int GetAbsMin(int *p,int len){std::sort(p,p+len);cout<<"after sort : ";ShowArray(p,len);int min=numeric_limits<int>::max();for(int i=1;i<len;i++){int tmp=abs(p[i]-p[i-1]);if(tmp<min)min=tmp;}return min;}void GetAbsMinTest(){int p[]={23,10,-10,8,-19,2,7,0,44,58,4};int len=sizeof(p)/sizeof(int);cout<<"the array : ";ShowArray(p,len);int min=GetAbsMin(p,len);cout<<"the minmal abs diff : "<<min<<endl;}/*2、写一个函数,检查字符是否是整数,如果是,返回其整数值。(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)*///这里在处理的时候没有考虑到正负数的问题,以及空格非法字符等。int MyAtio(char* str){int res=0;for(int i=0;str[i]!='\0';i++)res=res*10+str[i]-'0';return res;}int Atio(char* str){int sign=1;//先认为它是一个正数。int i=0;while(str[i]!='\0'&&str[i]==' ')i++;if(str[i]=='-'){sign=-1;i++;}if(str[i]=='+')i++;int res=0;for(;str[i]!='\0';i++)res=res*10+str[i]-'0';return sign==1?res:res*(-1);}void AtioTest(){char str[]="  +12340";cout<<"str : "<<str<<endl;int num=Atio(str);cout<<"str to num : "<<num<<endl;}/*3、给出一个函数来输出一个字符串的所有排列。思路:例如要输出abcd的全排列。对于第一个位置,可以取a、b、c、d四个。我们选取完以后,第一个位置处的字符就确定下来了。然后就是从第二个位置开始全排列。这里就是一个递归的过程例如一个字符str。下标从[low....high]。首先要选定low位置的字符。假定选择了i处的字符(low<=i<=high)。继续对[low+1....high]这些字符全排。排完之后要将i和low位置处的元素交换回来*/void StrArrange(char* str,int low,int high){if(low==high)cout<<str<<endl;else{for(int i=low;i<=high;i++){swap(str[low],str[i]);StrArrange(str,low+1,high);swap(str[low],str[i]);}}}void StrArrange(char* str){if(str==NULL)return;int high=strlen(str)-1;StrArrange(str,0,high);}void StrArrangeTest(){char str[]="abcd";cout<<"str : "<<str<<endl;cout<<"str arrange : "<<endl;StrArrange(str);}/*4、(a)请编写实现malloc()内存分配函数功能一样的代码。 (b)给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。思路:(a)实现内存分配比较难(b)主要是找到从哪个字符开始A的后几个字节开始和B的开始几个字节重叠。这里类似于字符串匹配。*///计算从哪个位置开始俩个开始重叠。其实就是字符串匹配的代码稍作修改即可int GetStrStartIndex(char* str,char* substr){int len=strlen(str);int len1=strlen(substr);int i=0,j=0;while(i<len){if(str[i]==substr[j]){i++;j++;if(i==len)return i-j;}else{i=i-j+1;j=0;}}return len;}void CopyAB(char* str,char* substr,char* output){int index=GetStrStartIndex(str,substr);int len1=strlen(substr);int i=0,j=0,k=0;//拷贝的时候先拷贝A中的字符,一直到index。while(i<index){output[k]=str[i];k++;i++;}//到了index就可以开始拷贝B中的字符了while(j<=len1){output[k]=substr[j];k++;j++;}}void GetStrStartIndexTest(){char str[]="hello world!";char substr[]="ldlhh";char output[50];cout<<"str : "<<str<<endl;cout<<"substr : "<<substr<<endl;int index=GetStrStartIndex(str,substr);cout<<"start index : "<<index<<endl;CopyAB(str,substr,output);cout<<"merge str and substr : "<<output<<endl;}/*5、怎样编写一个程序,把一个有序整数数组放到二叉树中?思路:这是一个递归的过程。例如数组p[low...mid.....high]。那么我们让p[mid]作为根节点。p[low...mid-1]作为左子树。p[mid+1....high]作为右子树。如果low>high。那么节点为空如果low==high。那么将p[low]作为节点值如果low<high。分为俩部分去递归*/void PutArrayInTree(int *p,int low,int high,TreeNode* &root){if(low>high)root=NULL;else if(low==high)root=new TreeNode(p[low]);else{int mid=low+(high-low)/2;root=new TreeNode(p[mid]);PutArrayInTree(p,low,mid-1,root->left);PutArrayInTree(p,mid+1,high,root->right);}}void PutArrayInTreeTest(){int p[]={20,10,-1,5,19,7,-2,0,3,17,2,22,-15};int len=sizeof(p)/sizeof(int);cout<<"the array : ";ShowArray(p,len);std::sort(p,p+len);cout<<"after sort : ";ShowArray(p,len);TreeNode* root=NULL;PutArrayInTree(p,0,len-1,root);cout<<"MidOrderTraverse : ";MidOrderTraverse(root);cout<<endl;}/*6、怎样从顶部开始逐层打印二叉树结点数据?请编程。  思路:二叉树的层序遍历属于广度遍历。所以我们借助队列来完成。开始队列中只有一个根节点。我们访问这个节点,然后判断这个节点是不是存在左右子节点。存在的话就进队。只要队列不为空。每次从队列头部弹出一个元素。访问这个元素。并且将这个元素的左右子节点进队。*/void LayerTraverse(TreeNode* root){if(root==NULL)return;queue<TreeNode*> qu;TreeNode *last=root;qu.push(root);while(!qu.empty()){TreeNode *root=qu.front();cout<<root->data<<" ";if(root->left!=NULL)qu.push(root->left);if(root->right!=NULL)qu.push(root->right);if(last==root){if(!qu.empty())last=qu.back();cout<<endl;}qu.pop();}}void LayerTraverseTest(){int p[]={20,10,-1,5,19,7,-2,0,3,17,2,22,-15};int len=sizeof(p)/sizeof(int);cout<<"the array : ";ShowArray(p,len);std::sort(p,p+len);cout<<"after sort : ";ShowArray(p,len);TreeNode* root=NULL;PutArrayInTree(p,0,len-1,root);cout<<"MidOrderTraverse : ";MidOrderTraverse(root);cout<<endl;cout<<"LayerTraverse : ";LayerTraverse(root);cout<<endl;}/*7、怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?思路:假如有一个头结点为head的单链表。如果head==NULL。直接返回如果head->next==NULL。说明链表中只有一个元素。直接返回。否则至少有俩个元素。*/void ReverseList(ListNode* &head){if(head==NULL)return;if(head->next==NULL)return;ListNode* pre=NULL;ListNode* p=head;while(p!=NULL){ListNode* q=p->next;p->next=pre;pre=p;p=q;}head=pre;}//建立一个链表void MakeList(ListNode* &head){int value=0;while(cin>>value){if(head==NULL)head=new ListNode(value);else{ListNode *node=new ListNode(value);node->next=head;head=node;}}}//打印一个链表void ShowList(ListNode *head){while(head!=NULL){cout<<head->data<<" ";head=head->next;}cout<<endl;}void ShowListReverseTest(){cout<<"make a list , input values "<<endl;ListNode* head=NULL;MakeList(head);cout<<"the list : ";ShowList(head);cout<<"show list from end to head : ";ReverseList(head);ShowList(head);cout<<endl;}/*9、编程实现两个正整数的除法编程实现两个正整数的除法,当然不能用除法操作符。// return x/y.int div(const int x, const int y) {  ....}*/int Div(const int x, const int y,int low,int high){if(low==high)return low;if(low+1==high){if(high*y<=x)return high;if(y*low<=x&&high*y>x)return low;}int mid=low+((high-low)>>1);if(mid*y>x)return Div( x, y,low,mid-1);elsereturn Div( x, y,mid,high);}int Div(const int x, const int y) {int low=1,high=x;return Div(x, y,low,high);}void DivTest(){cout<<"input x : ";int x=0;cin>>x;cout<<"input y : ";int y=0;cin>>y;cout<<"x/y : "<<Div(x,y)<<endl;}/*10、在排序数组中,找出给定数字的出现次数比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。*/int UpperBound(int *p,int low,int high,int n){if(low==high)return low;if(low+1==high){if(p[high]==n)return high+1;if(p[low]==n)return high;}int mid=low+(high-low)/2;if(p[mid]>n)return UpperBound(p,low,mid,n);elsereturn UpperBound(p,mid,high,n);}int LowerBound(int *p,int low,int high,int n){if(low==high)return low;int mid=low+(high-low)/2;if(p[mid]>=n)return LowerBound(p,low,mid,n);elsereturn LowerBound(p,mid+1,high,n);}void BoundTest(){int p[]={20,10,-1,5,19,7,-2,0,3,17,2,22,-15,2,19,10,2,22,19};int len=sizeof(p)/sizeof(int);cout<<"the array : ";ShowArray(p,len);std::sort(p,p+len);cout<<"after sort : ";ShowArray(p,len);int low=0,high=len-1;int n=0;cout<<"input a num : ";cin>>n;int lowindex=LowerBound(p,low,high,n);int highindex=UpperBound(p,low,high,n);cout<<"lowerbound : "<<lowindex<<endl;cout<<"upperbound : "<<highindex<<endl;}int _tmain(int argc, _TCHAR* argv[]){BoundTest();return 0;}


原创粉丝点击