[转]微软面试技术题
1 反转一个链表。循环算法。
List reverse(List l) {
if(!l) return l;
list cur = l.next;
list pre = l;
list tmp;
pre.next = null;
while ( cur ) {
tmp = cur;
cur = cur.next;
tmp.next = pre
pre = tmp;
}
return tmp;
}
2 反转一个链表。递归算法。
List resverse(list l) {
if(!l || !l.next) return l;
List n = reverse(l.next);
l.next.next = l;
l.next=null;
}
return n;
}
3 广度优先遍历二叉树。
void BST(Tree t) {
Queue q = new Queue();
q.enque(t);
Tree t = q.deque();
while(t) {
System.out.println(t.value);
q.enque(t.left);
q.enque(t.right);
t = q.deque();
}
}
class Node {
Tree t;
Node next;
}
class Queue {
Node head;
Node tail;
public void enque(Tree t){
Node n = new Node();
n.t = t;
if(!tail){
tail = head = n;
} else {
tail.next = n;
tail = n;
}
}
public Tree deque() {
if (!head) {
return null;
} else {
Node n = head;
head = head.next;
return n.t;
}
}
4 输出一个字符串所有排列。注意有重复字符。
char[] p;
void perm(char s[], int i, int n){
int j;
char temp;
for(j=0;j<n;++j){
if(j!=0 && s[j]==s[j-1]);
elseif(s[j]!='@'){
p[i]=s[j];
s[j]='@';
if(i==n-1){
p[n]='\0';
printf("%s", p);
}else{
perm(s,i+1,n);
}
s[j]=p[i];
}
}
}
void main() {
char s[N];
sort(s);
perm(s,0,strlen(s));
}
5 输入一个字符串,输出长型整数。
long atol(char *str){
char *p = str;
long l=1;m=0;
if (*p=='-') {
l=-1;
++p;
}
while(isDigit(*p)){
m = m*10 + p;
++p;
}
if(!p) return m*l;
else return error;
}
判断一个链表是否有循环。
int isLoop(List l) {
if ( ! l) return - 1 ;
List s = l.next;
while (s && s != l) {
s = s.next;
}
if ( ! s) return - 1 ;
else reutrn 1 ;
}
int isLoop(List l){
if(!l) return 0;
p=l.next;
wihle(p!=l&&p!=null) {
l.next=l;
l=p;p=p.next;
}
if(p=l) return 1;
return 0;
}
实际上,在我的面试过程中,还问到了不破坏结构的其他算法。
我的答案是从链表头开始遍历,如果节点next指针指向自身,则循环存在;否则将next指针指向自身,遍历下一个节点。直至next指针为空,此时链表无循环。
反转一个字符串。
void reverse( char * str) {
char tmp;
int len;
len = strlen(str);
for ( int i = 0 ;i < len / 2 ; ++ i) {
tmp = char [i];
str[i] = str[len - i - 1 ];
str[len - i - 1 ] = tmp;
}
}
实现strstr函数。
int strstr(char[] str, char[] par){
int i=0;
int j=0;
while(str[i] && str[j]){
if(str[i]==par[j]){
++i;
++j;
}else{
i=i-j+1;
j=0;
}
}
if(!str[j]) return i-strlen(par);
else return -1;
}
实现strcmp函数。
int strcmp(char* str1, char* str2){
while(*str1 && *str2 && *str1==*str2){
++str1;
++str2;
}
return *str1-*str2;
}
求一个整形中1的位数。
int f( int x) {
int n = 0 ;
while (x) {
++ n;
x &= x - 1 ;
}
return n;
}
汉诺塔问题。
void tower(n,x,y,z){
if(n==1) move(x,z);
else {
tower(n-1, x,z,y);
move(x,z);
tower(n-1, y,x,z);
}
}
三柱汉诺塔最小步数。
int f3(n) {
if (f3[n]) return f3[n];
else {
if (n == 1 ) {
f3[n] = 1 ;
return 1 ;
}
f3[n] = 2 * f3(n - 1 ) + 1 ;
return f3[n];
}
}
四柱汉诺塔最小步数。
int f4(n){
if(f4[n]==0){
if(n==1) {
f4[1]==1;
return 1;
}
min=2*f4(1)+f3(n-1);
for(int i=2;i<n;++i){
u=2*f4(i)+f3(n-i);
if(u<min) min=u;
}
f4[n]=min;
return min;
} else return f4[n];
}
在一个链表中删除另一个链表中的元素。
void delete(List m, List n) {
if(!m || !n) return;
List pre = new List();
pre.next=m;
List a=m, b=n,head=pre;
while(a && b){
if(a.value < b.value) {
a=a.next;
pre=pre.next;
}else if(a.value > b.value){
b=b.next;
}else{
a=a.next;
pre.next=a;
}
}
m=head.next;
}
一个数组,下标从0到n,元素为从0到n的整数。判断其中是否有重复元素。
int hasDuplicate(int[] a, int n){
for(int i=0;i<n;++i){
while(a[i]!=i && a[i]!=-1){
if(a[a[i]]==-1) return 1;
a[i]=a[a[i]];
a[a[i]]=-1;
}
if(a[i]==i) {a[i]=-1;}
}
return 0;
}
返回一颗二叉树的深度。
int depth(Tree t){
if(!t) return 0;
else {
int a=depth(t.right);
int b=depth(t.left);
return (a>b)?(a+1):(b+1);
}
}
两个链表,
List merge(List a, List d) {
List a1 = reverse(d);
List p = q = new List();
while ( a && a1 ) {
if (a.value < a1.value) {
p.next = a;
a = a.next;
} else {
p.next = a1;
a1 = a1.next;
}
p = p.next;
}
if (a) p.next = a;
elseif(a1) p.next = a1;
return q.next;
}
将长型转换为字符串。
char* ltoa(long l){
char[N] str;
int i=1,n=1;
while(!(l/i<10)){i*=10;++n}
char* str=(char*)malloc(n*sizeof(char));
int j=0;
while(l){
str[j++]=l/i;
l=l%i;
i/=10;
}
return str;
}
在双向链表中删除指定元素。
void
List pre=new List();
pre.next = head;
List cur = head;
while(cur && cur!=node){
cur=cur.next;
pre=pre.next;
}
if(!cur) return;
List post = cur.next;
pre.next=cur.next;
post.last=cur.last;
return;
}
不重复地输出升序数组中的元素。
void outputUnique( char [] str, int n) {
if (n <= 0 ) return ;
elseif(n == 1 ) putchar(str[ 0 ]);
else {
int i = 0 ,j = 1 ;
putchar(str[ 0 ]);
while (j < n) {
if (str[j] !== str[i]) {
putchar(str[j]);
i = j;
}
++ j;
}
}
}
面试过程中我还遇到了下面几题:
1、如何删除链表的倒数第m的元素?我的方法是先用pre指针从链表头开始步进m,新建pst节点 next指针指向头节点,cur指针指向头节点,然后pre,cur,post三个指针一起步进,当pre指向链表结尾的时候cur指向倒数第m个元素, 最后利用pst指针删除cur指向元素。
2、如何判断一个字符串是对称的?如a,aa,aba。设置头尾指针同时向中间比较靠齐直至相遇。
3、如何利用2函数找出一个字符串中的所有对称子串?以子串头指针和尾指针为循环变量设置两个嵌套的循环以找出所有子串,对每个子串应用2函数。
第1题想法不错,就只要扫描一遍.
而第3题是效率的问题,如果这样,估计微软不满意.
时间复杂度要达到o(N^3).太慢了.
--------
其他题目:
1.链表和数组的区别在哪里?
2.编写实现链表排序的一种算法。说明为什么你会选择用这样的方法?
3.编写实现数组排序的一种算法。说明为什么你会选择用这样的方法?
4.请编写能直接实现strstr()函数功能的代码。
5.编写反转字符串的程序,要求优化速度、优化空间。
6.在链表里如何发现循环链接?
7.给出洗牌的一个算法,并将洗好的牌存储在一个整形数组里。
8.写一个函数,检查字符是否是整数,如果是,返回其整数值。(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)
9.给出一个函数来输出一个字符串的所有排列。
10.请编写实现malloc()内存分配函数功能一样的代码。
11.给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。
12.怎样编写一个程序,把一个有序整数数组放到二叉树中?
13.怎样从顶部开始逐层打印二叉树结点数据?请编程。
14.怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?
---------------------
微软亚洲
1.进程和线程的差别。
线程是指进程内的一个执行单元,也是进程内的可调度实体.
与进程的区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
2.
人工测试:个人复查、抽查和会审
机器测试:黑盒测试和白盒测试
2.Heap与stack的差别。
Heap是堆,stack是栈。
Stack的
Stack空间有限,Heap是很大的自由
C中的malloc函数分配的
程序在编译期对变量和函数分配内存都在栈上进行,且程序运行过程中函数调用时参数的传递也在栈上进行
3.Windows下的内存是如何管理的?
4.介绍.Net和.Net的安全性。
5.客户端如何访问.Net组件实现Web Service?
6.C/C++编译器中虚表是如何完成的?
7.谈谈COM的线程模型。然后讨论进程内/外组件的差别。
8.谈谈IA32下的分页机制
小页(4K)两级分页模式,大页(4M)一级
9.给两个变量,如何找出一个带环单链表中是什么地方出现环的?
一个递增一,一个递增二,他们指向同一个接点时就是环出现的地方
10.在IA32中一共有多少种办法从用户态跳到内核态?
通过调用门,从ring3到ring0,中断从ring3到ring0,进入vm86等等
11.如果只想让程序有一个实例运行,不能运行两个。像winamp一样,只能开一个窗口,怎样实现?
用内存映射或全局原子(互斥变量)、查找窗口句柄..
FindWindow,互斥,写标志到文件或注册表,共享内存。.
12.如何截取键盘的响应,让所有的‘a’变成‘b’?
键盘钩子SetWindowsHookEx
13.Apartment在COM中有什么用?为什么要引入?
14.存储过程是什么?有什么用?有什么优点?
我的理解就是一堆sql的集合,可以建立非常复杂的查询,编译运行,所以运行一次后,以后再运行速度比单独执行SQL快很多
15.Template有什么特点?什么时候用?
16.谈谈Windows DNA结构的特点和优点。
----------
单链表逆序(c#版)
面试题解(1):单向链表相关
面试题解(2):loop相关
逆转单向链表
Data Structures and Algorithms with Object-Oriented Design Patterns in C#