微软十五道面试题 答案

一、微软十五道面试题

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<=i,j<=n)可以表示成B中第i个到第j-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题目:回溯法即可 http://blog.csdn.net/u012605629/article/details/40121259

#include<iostream>
#include<stdio.h>
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<n;i++)
			printf("%c",a[i]);
		printf("\n");
		return ;
	}
	for(j=index;j<n;j++)
	{
		swap(&a[index],&a[j]);
		printAllArray(a,n,index+1);
		swap(&a[index],&a[j]);
	}
}
int main()
{
	char a[]="abcd";
	char b[]="swg";
	int len;
	//len=sizeof(a)/sizeof(char);//5
	len=strlen(a);
	printAllArray(a,len,0);//4*3*2=24种 
	
	printf("*****************\n");
	len=strlen(b);
	printAllArray(b,len,0);//3*2=6种 
	
	return 0;
}


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


malloc()是C语言中动态存储管理的一组标准库函数之一。
其作用是在内存的动态存储区中分配一个长度为size的连续空间。
其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针
我觉得要用到系统调用了 操作系统了


(b)同85题目  http://blog.csdn.net/u012605629/article/details/40429029
#include<iostream>
#include<stdio.h>
#include<string.h>
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<len;i++)//遍历a 开始查找当前i位置到结束是否是b的前缀 
	{
		k=i;j=0;
		while(a[k]==b[j])
		{
			k++;j++;
			if(k==len)
			{
				f=1;
				break;
			}	
		}
		if(f==1)
			break;
	}
	len2=strlen(b);
	for(k=0;k<i;k++)//从i开始 与b前面相同 
		c[k]=a[k];
	for(j=0;j<len2;k++,j++)
		c[k]=b[j]; 
	
	for(i=0;i<k;i++)
		printf("%c",c[i]);
	printf("\n");
}


int main()
{
	char a[]={"12345678"};
	char b[]={"56789322"};
	printf("串1:%s 串2:%s\n",a,b);
	printf("合并后的串为:"); 
	myStrcpy(a,b);
	
	char c[]={"fgaercxore"};
	char d[]={"ekkkkkkkfff"};
	printf("串1:%s 串2:%s\n",c,d);
	printf("合并后的串为:"); 
	myStrcpy(c,d);
	return 0;
} 


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

同86题  http://blog.csdn.net/u012605629/article/details/40429125
有序的,直接中间分开 左右子树建立递归 
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
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题  http://blog.csdn.net/u012605629/article/details/39316929
/*
第 16  题:
题目(微软): 
输入一颗二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。
		8
      /  \
	 6   10
	/ \  / \
   5  7 9  11
打印出来:8 6 10 5 7 9 11


BFS广度优先搜索 




#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<queue> 
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<BTreeNode *> 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  题: http://blog.csdn.net/u012605629/article/details/39377099
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题: http://blog.csdn.net/u012605629/article/details/40454357
#include<iostream>
#include<stdio.h>
#include<string.h>
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') 
	{
		ans=ans*10+(*p-'0');
		p++;
	}
	return ans;
}
int main()
{
	
	char a[]={"+123"};
	printf("%s:符串转整型为:%d\n",a,atoi(a)); 
	
	char b[]={"-123"};
	printf("%s:符串转整型为:%d\n",b,atoi(b)); 
	
	char c[]={"123CS45"};
	printf("%s:符串转整型为:%d\n",c,atoi(c)); 
	
	char d[]={"123.45CS"};
	printf("%s:符串转整型为:%d\n",d,atoi(d)); 
	
	char e[]={"CS123.45"};
	printf("%s:符串转整型为:%d\n",e,atoi(e));
	return 0;
} 


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)<max(k(AB), k(BC))
其中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题  http://blog.csdn.net/u012605629/article/details/40084961
/*
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<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;


bool checkGaps(int a[],int s,int e,int allowGaps)
{
	int i=s;
	while(i<e)
	{
		allowGaps-=a[i+1]-(a[i]+1);
		if(allowGaps<0)
			return false;
		i++;
	}
	return true;
}


bool isStraight(int a[])
{
	sort(a,a+5);
	if(a[0]>0)
		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<5;i++)
		printf("%d",a[i]);
	if(isStraight(a))
		printf(" is straight.\n");
	else
		printf(" is not straight.\n");
		
		
	for(i=0;i<5;i++)
		printf("%d",b[i]);
	if(isStraight(b))
		printf(" is straight.\n");
	else
		printf(" is not straight.\n");
		
		
	for(i=0;i<5;i++)
		printf("%d",c[i]);
	if(isStraight(c))
		printf(" is straight.\n");
	else
		printf(" is not straight.\n");
	
	return 0;
} 


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

同75题:http://blog.csdn.net/u012605629/article/details/40159015

/*
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<= mid)
    {
        if (root.Right == null)
            return root;
        BinNode find=FindNode(root.Right, mid);
        //不一定找得到
        return find.Element < mid ? root : find;
    }
    //如果大于,则找到Left
    else  //temp.Element > find
    {
        if (root.Left == null)
            return root;
        BinNode find = FindNode(root.Left, mid);
        //不一定找得到
        return find.Element < mid ? root : find;
    }
}  


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<e)
	{
		if(sum<dest) 
			sum=sum-*f+*(++f);
		else
			sum=sum-*e+*(--e);
	}
	if(sum==dest)
		printf("%d+%d=%d\n",*f,*e,dest);
}

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<len;i++)  
        b[i]=sum-a[i];  
    int high = len-1;  
    int low = 0;  
    while(low<high)  
    {  
        if(a[low]==b[high])  
        {  
            cout<<a[high]<<" + "<<b[high]<<" = "<<sum<<endl;  
            low++;  
            high--;  
        }else if(a[low] > b[high])  
        {  
            high--;  
        }else{  
            low++;  
        }  
    }  
    getchar();  
    return 0;  
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,下面是一些常见的C#和WPF的面试题答案: 1. 什么是C#? C#是一种面向对象的编程语言,由微软公司开发。它是.NET平台的一部分,用于开发各种应用程序,包括桌面应用程序、Web应用程序、移动应用程序等。 2. C#中的类型和引用类型有什么区别? 类型直接包含其数据,存储在堆栈上,而引用类型存储在堆上,并且变量存储的是对数据的引用。类型的赋是将进行复制,而引用类型的赋是将引用进行复制。 3. C#中的接口和抽象类有什么区别? 接口是一种完全抽象的类,它定义了一组方法和属性,但没有实现。它被用于实现多态性和类之间的松耦合。抽象类是一个可以包含实现代码的类,它可以有抽象成员和非抽象成员。一个类只能继承一个抽象类,但可以实现多个接口。 4. 什么是WPF? WPF(Windows Presentation Foundation)是微软公司开发的一种用于创建用户界面的技术。它使用XAML(eXtensible Application Markup Language)来定义界面,提供了强大的UI布局和数据绑定功能。 5. WPF中的MVVM模式是什么? MVVM(Model-View-ViewModel)是一种设计模式,用于在WPF应用程序中实现分离UI逻辑和业务逻辑。模型(Model)表示应用程序的数据,视图(View)表示用户界面,视图模型(ViewModel)是视图和模型之间的中介,负责处理用户输入、数据绑定和其他逻辑。 6. WPF中的数据绑定有哪些方式? WPF中的数据绑定有多种方式,包括: - 单向绑定:将数据从源绑定到目标,只能源更新目标。 - 双向绑定:将数据从源绑定到目标,并且可以在目标或源上进行更改。 - 单向到源绑定:将数据从目标绑定到源,只能目标更新源。 7. WPF中的命令是什么? 命令是一种用于处理用户交互的行为的机制。WPF中的命令实现了ICommand接口,可以通过命令来处理按钮点击、菜单项选择等操作。 这些问题只是一些常见的C#和WPF面试题,您可能会遇到更具体的问题,所以建议您对这些主题进行更详细的学习和准备。希望对您有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值