一、微软十五道面试题
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、有一个整数数组,请求出两两之差绝对值最小的值,
记住,只要得出最小值即可,不需要求出是哪两个数。
解法:
方法一:
先排序,然后比较相邻两数的差的绝对值,最后就可以得到最小的绝对值。如果用计数排序,复杂度是n。
方法二:
设这个整数数组是a1,a2,…,an
构造数组B=(b1,b2,…,bn-1)
b1 = a1-a2,
b2 = a2-a3,
b3 = a3-a4,
…
bn-1 = an-1 – an
那么原数组中,任意两整数之差ai-aj(1
例如b2+b3+b4 = (a2-a3) + (a3-a4) + (a4-a5) = a2-a5
O(n)构造出B序列后,用类似“最大子段和”算法求“最小绝对值子段和”
2、写一个函数,检查字符是否是整数,如果是,返回其整数值。
(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)
long strToInt(char *str,int length)//从最左边开始
{
if(length>1)
return str[0]=='-'? strToInt(str,length-1)*10-(str[length-1]-'0') : strToInt(str,length-1)*10+str[length-1]-'0';
else
return str[0]=='-'? 0:str[0]-'0';
}
递归过程
-23 ==> f(-2)*10-3 ==> ( f(-)*10-2 )*10-3 ==> (0*10-2)*10-3= -23
3、给出一个函数来输出一个字符串的所有排列。
同70题目:回溯法即可
#include
#include
using namespace std;
void swap(char *a,char *b)
{
char t;
t=*a;
*a=*b;
*b=t;
}
void printAllArray(char a[],int n,int index)
{
int i,j;
if(index==n)
{
for(i=0;i
4( a)请编写实现 malloc()内存分配函数功能一样的代码。
(b) 给出一个函数来复制两个字符串A和 B。字符串A的后几个字节和字符串B的前几个字节重叠。
malloc()是C语言中动态存储管理的一组标准库函数之一。
其作用是在内存的动态存储区中分配一个长度为size的连续空间。
其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针
我觉得要用到系统调用了 操作系统了
(b)同85题目
#include
#include
#include
using namespace std;
#define N 101
void myStrcpy(char a[],char b[])
{
char c[N];
int len,len2,i,j,k,f;
len=strlen(a);
f=0;
for(i=0;i
5、怎样编写一个程序,把一个有序整数数组放到二叉树中?
同86题
有序的,直接中间分开 左右子树建立递归
#include
#include
#include
#include
using namespace std;
#define N 101
struct Node{
int data;
struct Node *left,*right;
};
Node* bulidTree(int array[], int start, int end)
{
if (start>end)
return NULL;
int m=(start+end)/2;
Node *root=(Node*)malloc(sizeof(Node));
root->data=array[m];
root->left=bulidTree(array,start,m-1);
root->right=bulidTree(array,m+1,end);
return root;
}
// 中序遍历 左根右
void displayTreeMid(Node *head)
{
if(head->left)
displayTreeMid(head->left);
printf("%d ",head->data);
if(head->right)
displayTreeMid(head->right);
}
// 前序遍历 根左右
void displayTreeFore(Node *head)
{
printf("%d ",head->data);
if(head->left)
displayTreeFore(head->left);
if(head->right)
displayTreeFore(head->right);
}
// 后序遍历 左右根
void displayTreeBack(Node *head)
{
if(head->left)
displayTreeBack(head->left);
if(head->right)
displayTreeBack(head->right);
printf("%d ",head->data);
}
int main()
{
/*
5
2 7
1 3 6 8
4 9
中序遍历:1 2 3 4 5 6 7 8 9
前序遍历:5 2 1 3 4 7 6 8 9
后序遍历:1 4 3 2 6 9 8 7 5
*//*
int array[]={1,2,3,4,5,6,7,8,9};
Node *root;
root=bulidTree(array,0,sizeof(array)/sizeof(int)-1);
printf("中序遍历:");
displayTreeMid(root);
printf("n");
printf("前序遍历:");
displayTreeFore(root);
printf("n");
printf("后序遍历:");
displayTreeBack(root);
printf("n");
return 0;
}
6、怎样从顶部开始逐层打印二叉树结点数据?请编程。
同16题
/*
第 16 题:
题目(微软):
输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。
8
/
6 10
/ /
5 7 9 11
打印出来:8 6 10 5 7 9 11
BFS广度优先搜索
#include
#include
#include
#include
using namespace std;
#define MAX 20
struct BTreeNode{
int data;
BTreeNode *left,*right;
};
//建立二叉树
BTreeNode * CreateTree(int data[],int pos,int len)
{
BTreeNode *tree;
if(pos>=len)
{
return NULL;
}
else
{
tree=(BTreeNode *)malloc(sizeof(BTreeNode));
tree->data=data[pos];
tree->left=CreateTree(data,2*pos+1,len);//数组坐标
tree->right=CreateTree(data,2*pos+2,len);
return tree;
}
}
void InOrder(BTreeNode *tree)
{
if(tree!=NULL)
{
InOrder(tree->left);
printf("%d ",tree->data);
InOrder(tree->right);
}
}
void BFS(BTreeNode *root)
{
BTreeNode *temp,*start;
queue q;
q.push(root);
while(!q.empty())
{
start=q.front();
q.pop();
if(start->left!=NULL)
q.push(start->left);
if(start->right!=NULL)
q.push(start->right);
printf("%d ",start->data);
}
}
int main(){
int data[]={8,6,10,5,7,9,11};
int len=sizeof(data)/sizeof(int);
BTreeNode *tree=CreateTree(data,0,len);
printf("中序遍历:n");//左根右
InOrder(tree);printf("n");
printf("打印结果:n");
BFS(tree);printf("n");
return 0;
}
7、怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?
同 第 24 题:
node * reverseNonrecurse(node *head)
{
if(head==NULL) return head;
node *p=head,*previous=NULL,*next=NULL;
while(p->next!=NULL)
{
next=p->next;//保存下一个
p->next=previous;//p下一个为他前面的
previous=p;
p=next;
}
p->next=previous;
return p;
}
8、请编写能直接实现 int atoi(const char * pstr) 函数功能的代码。
同89题:
#include
#include
#include
using namespace std;
int atoi(char* a)
{
if (*a=='+')
return atoi(a+1);
else if(*a=='-')
return -atoi(a+1);
char *p=a;
int ans=0;
while(*p>='0'&&*p
9、编程实现两个正整数的除法
编程实现两个正整数的除法,当然不能用除法操作符。
// return x/y.
int div(const int x, const int y)
{
….
}
解法 循环模拟
void devide(int val1, int val2, int& res, int &rev) //两个值val1 val2 商res 余数rev
{
int maxv = max(val1, val2);
int minv = min(val1, val2);
res=0; rev = 0;
if(maxv == minv){
res = 1;
rev = 0;
return;
}
else
{
while(maxv>minv)
{
maxv=maxv-minv;
res+=1;
}
rev=maxv;
return;
}
}
10、在排序数组中,找出给定数字的出现次数
比如 [1, 2, 2, 2, 3]中2的出现次数是3次。
我不管有没排好序 二分查找
void countNum(int a[],int start,int finish,int num)
{
int middle=(start+finish)/2;
if(start>finish)
return ;
if(a[middle]==num)
{
count++;
countNum(a,start,middle-1,num);
countNum(a,middle+1,finish,num);
}
else if(a[middle]>num)
countNum(a,start,middle-1);
else
countNum(a,middle+1,finish);
}
11、平面上N个点,每两个点都确定一条直线,
求出斜率最大的那条直线所通过的两个点(斜率不存在的情况不考虑)。时间效率越高越好。
3个点A,B,C,把它们的按x坐标排序。假设排序后的顺序是ABC,那么有两种情况:
1.ABC共线,则k(AB)=k(BC)=k(AC)
2.ABC不共线,则ABC将形成一个三角形,那么k(AC)
其中k()表示求斜率。
所以程序的基本步骤就是:
1.把N个点按x坐标排序。
2.遍历,求相邻的两个点的斜率,找最大值。
时间复杂度Nlog(N)。
先把这些点按x坐标从小到大排序,斜率最大的两点必然是挨一起的两个点,
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的最小值和最大值,两者只差小于5即连续相邻
给出一个类似的题目 67题
/*
67.俩个闲玩娱乐。
1.扑克牌的顺子
从扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这 5 张牌是不是连续的。2-10 为数
字本身,A为1,J 11,Q为12,K为13,而大小王可以看成任意数字。
5张牌看成由5个数字组成的数组。大小王当成0.我们把数组排序。由于0可以当成任意数字,
我们可以用0去补满数组中的空缺。也就是排序之后的数组不是连续的,
即相邻的两个数字相隔若干个数字,但如果我们有足够的0可以补满这两个数字的空缺,
这个数组实际上还是连续的。
{0,1,3,4,5}。0可以当成2去填补这个空缺,所以是顺子
*/
#include
#include
#include
using namespace std;
bool checkGaps(int a[],int s,int e,int allowGaps)
{
int i=s;
while(i0)
return checkGaps(a,0,4,0);
else if(a[0]==0&&a[1]!=0)
return checkGaps(a,1,4,1);
return checkGaps(a,2,4,2);
}
int main()
{
int i;
int a[]={1,0,3,4,5};
int b[]={0,0,9,5,6};
int c[]={1,0,2,3,6};
for(i=0;i
13、设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
复杂度如果是 O(n2)则不得分。
同75题:
/*
75.二叉树两个结点的最低共同父结点
题目:二叉树的结点定义如下:
struct TreeNode
{
int m_nvalue;
TreeNode* m_pLeft;
TreeNode* m_pRight;
};
输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。
对于一个子树的根结点来说,如果那两个结点分别位于该子树的左右子树,则最低共同父结点为该子树的根结点,
如果那两个结点都位于该子树的左子树,则最低共同父结点位于该子树根结点的左子树,
否则来自右子树。递归
*/
//寻找二叉树两个结点的最低共同父节点
TreeNode *FindFirstCommonParentNode(TreeNode *pRoot, TreeNode *pNodeOne, TreeNode *pNodeTwo)
{
if (NULL==pRoot)
{
return NULL;
}
if (pRoot==pNodeOne || pRoot==pNodeTwo)
{
return pRoot;
}
TreeNode *pLeft = FindFirstCommonParentNode(pRoot->m_pLeft, pNodeOne, pNodeTwo);
TreeNode *pRight = FindFirstCommonParentNode(pRoot->m_pRight, pNodeOne, pNodeTwo);
if (NULL==pLeft) //1、左子树没有找到任何一个结点,则第一个公共父节点必定在右子树,而且找到第一个结点就是最低共同父节点
{
return pRight;
}
else if (NULL==pRight) //2、右子树没有找到任何一个结点,则第一个公共父节点必定在左子树,而且找到第一个结点就是最低共同父节点
{
return pLeft;
}
else //3、分别在结点的左右子树找到,则此节点必为第一个公共父节点
{
return pRoot;
}
}
14、一棵排序二叉树,令 f=(最大值+最小值)/2,
设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是 O(n2)则不得分。
算法思想:最小最大节点分别在最左下与最右下节点,O(N)
static BinNode Find(BinNode root)
{
BinNode min = FindMinNode(root);
BinNode max = FindMaxNode(root);
double find = (double)(min.Element+max.Element) / 2;
return FindNode(root, find);
}
static BinNode FindMinNode(BinNode root)
{
BinNode min = root;
while (min.Left != null)
{
min = min.Left;
}
return min;
}
static BinNode FindMaxNode(BinNode root)
{
BinNode max = root;
while (max.Right != null)
{
max = max.Right;
}
return max;
}
递归寻找BST的节点,O(logN)。
static BinNode FindNode(BinNode root, double mid)
{
//如果小于相等,则从右边找一个最小值
if (root.Element find
{
if (root.Left == null)
return root;
BinNode find = FindNode(root.Left, mid);
//不一定找得到
return find.Element
15、一个整数数列,元素取值可能是 1~N (N 是一个较大的正整数)中的任意一个数,相
同数值不会重复出现。
设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
复杂度最好是 O(n),如果是 O(n2)则不得分。
1、前后双指针(但是有排序过程要做,这个费时看情况)最快也是O(nlgn)
void find2Number(int a[],int n,int dest)
{
int *f=a,*e=a+n-1;
int sum=*f+*e;
while(sum!=dest&&f
2.用空换时间的做法:
int main()
{
int a[] = {1,3,4,7,8,9,10};
int sum = 11;
int len = sizeof(a)/sizeof(int);
int *b = (int *)malloc(sizeof(len));
for(int i=0;i b[high])
{
high--;
}else{
low++;
}
}
getchar();
return 0;
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net