微软等数据结构+算法面试100题(47)-- 微软三道面试题
2012-11-12 10:25
465 查看
微软三道面试题
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进制那方面想)
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进制那方面想)
/* 1. 给一个有N个整数的数组S..和另一个整数X,判断S里有没有2个数的和为X, 请设计成O(n*log2(n))的算法。 思路:先对数组排序时间复杂度是nlogn。排序完后设俩个下标low和high,分别指向最大和最小的元素。 如果p[low]+p[high]==x,找到。 如果p[low]+p[high]>x,high--。 如果p[low]+p[high]<x,low++。 当low>high的时候即可退出。 */ void GetSumX(int *p,int len,int x) { std::sort(p,p+len); int low=0,high=len-1; while(low<high) { if(p[low]+p[high]==x) { cout<<p[low]<<" + "<<p[high]<<endl; low++; } else if(p[low]+p[high]>x) high--; else low++; } }
/* 2. 有2个数组..里面有N个整数。 设计一个算法O(n log2(n)),看是否两个数组里存在一个同样的数。 思路:俩个数组,可以分别对俩个数组排序复杂度是nlogn。 接下来就是遍历俩个数组p,q。分别设俩个下标i,j指向数组的首部. 如果p[i]==q[j],找到了输出。 如果p[i]>q[j],那么j++; 如果p[i]<q[j],那么i++; 直到i>=len1或者j>=len2时。说明有一个数组已经遍历完。不可能再有一样的元素。退出。 */ void GetSameCellInArray(int *p,int len1,int *q,int len2) { std::sort(p,p+len1); std::sort(q,q+len2); int i=0,j=0; while(i<len1&&j<len2) { if(p[i]==q[j]) { cout<<p[i]<<" = "<<q[j]<<endl; i++; } else if(p[i]<q[j]) i++; else j++; } }
// 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); else return 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); else return 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); else return 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; }
相关文章推荐
- 微软等数据结构+算法面试100题(10)--三道面试题
- 微软等数据结构+算法面试100题(8)--华为面试题
- 微软等数据结构+算法面试100题(48)-- 微软十五道面试题
- 微软等数据结构+算法面试100题(18)--百度面试题
- 横空出世,席卷互联网--评微软等公司数据结构和算法面试100题
- 微软等数据结构+算法面试100题全部答案集锦
- 珍藏版、微软等数据结构+算法面试100题全部出炉
- [置顶]横空出世,席卷互联网--评微软等公司数据结构和算法面试100题
- 横空出世,席卷互联网--评微软等公司数据结构和算法面试100题 .
- 微软等数据结构+算法面试100题全部答案集锦
- 微软等数据结构+算法面试100题(35)-- 二叉树的深度
- 微软等数据结构+算法面试100题(44)-- 求子数组的最大和
- 横空出世,席卷互联网--评微软等公司数据结构和算法面试100题
- 微软等数据结构+算法面试100题[最新第61-80题]
- 评微软等公司数据结构和算法面试100题
- 微软等数据结构+算法面试100题全部答案集锦
- 微软等数据结构+算法面试100题(36)-- 打印二叉树中某一层的节点
- 微软等数据结构+算法面试100题(45)-- 在二元树中找出和为某一值的所有路径
- 微软等数据结构+算法面试100题全部答案集锦
- 横空出世,席卷互联网--评微软等公司数据结构和算法面试100题