从开始准备微软的笔试面试以来,大概有1个月了,看过微软的笔试题目,注重基础,全英文。答错了扣分的机制,告诉了笔试者最好不要回答答案模糊的题目。我就是冒险多答了几道题目,这几个题目都错了。分数拉低了不少,好在也过了笔试。
面试一共两个小时,一面和二面,根据我的经验,我觉得一面的结果很大程度上影响到二面。所以一面一定要做到面试的好坏达到中等以上才有机会。
我的一面面试的不理想,面试官首先问了一下实习的事情,介绍了实习做的相关工作,面试官对你所做的并不熟悉,但是他知道这个东西又是流行的,所以面试者应该逻辑清晰的把用到的技术解释给面试官听,这个沟通过程很重要,我做的不好。接下来是一道面试题目:
计算两个日期之间相差的天数。自己就是没有通过这道题目,痛心。以前看到过,但是一直没有做过,潜意识里认为这道题不会,当知道问这个题目的时候心都慌了。在思考怎样解题的时候,心里还是比较乱的。很快想了一个比较笨的方法,和面试官交流。希望可以通过面试官的提示,往更好的解题方式上靠。但是和面试官交流了思想之后,面试官并没有给我任何提示,直接叫我写代码了,自己想的方式判断比较多,思路简单的方法在写代码的时候遇到问题,现在想来,我就是没有考虑清楚就动手写代码了,以至于bug比较多。面试官查看代码的时候找出了很多bug。一面也就这样结束了。
二面的时候,面试官开始直接问了
如何设计一个分布式缓存系统,自己一听到这个题目,觉得又不会,因为前期准备的是算法题目,链表,数组,树,排序等等之类的东西。不过我觉得这个是开放型题目,可以很好的和面试官探讨问题。面试官问了,检验系统的指标。速度和安全等,一起如何解决备份,扩容等问题。回到学校和大家讨论的时候,大家觉得面试官可能是希望我回答处如何解决扩容问题,这个现在一般的方法是一致性hash方法,但是我不知道这个方法,在面试的时候,肯定是想不到这个点,一致性hash还需要好好看。接下来的面试题目有:写一个atoi函数,面试官当时的要求是要确实可以直接使用的函数,就是说这个题目要写的很完善。这道题目要考虑的点比较多,从输入的测试用例就可以看出来,函数内部要做什么:
测试用力:+111222,-1111222,+a1111,-11114a22,123.456,123*456,123空格456,123456789987654321(大数),我没有考虑到数字中间有空格的情况,和小数点的情况,这是面试官提出来的。其他我都考虑到了,在考虑大数对于INT变量会溢出的情况,我选择的方法是,使用long
long型变量tmp,记录中间结果,如果tmp大于INT_MAX说明要转换的字符串溢出了,面试官提示这个有错误,他给的例子是要是要求返回的是long
long型的结果,如何找到可以存储比long
long型更大的数呢?他说这道题目就要判断什么时候溢出,我想了一会,给出的方法是,如果一个正数加上一个正数后的结果比自己小,那就说明溢出了。然后的题目有,各种排序的时空复杂度,C/C++的static的区别,C++中多态的好处(这个我没有打上来,唉),如何找到第K大的数,我给出的方法有算则排序O(kn),堆排序(nlogm),快排近似为O(n)。
他又问了我怎样优化快排:
1 每次选择的key,可以是a【left】,a【middle】,a【right】中的第2大的数。
2
当快速排序的数组长度小于某一个值的时候,可以使用插入或者选择排序
这次面试也就到此为止了,一面决定了与不能去微软实习了,二面我个人觉得面试官是了解一面的结果的。
不过,虽然很遗憾,但是也看到微软的工作环境,等候室有免费的饮料和零食,这么好的公司环境自己去不了真是遗憾。努力,记住教训。还有机会。
//怎样判断溢出还需要看看资料 。
//一致性hash算法的应用还需要看。
//c++多态,使用多态的好处。
//如何设计一个缓存系统
1//计算两个日期相差的天数(润年)
2//atoi函数
3//find
top(k)。
自己贴上1 的两种代码:(gcc 版本 4.6.3 (Ubuntu/Linaro
4.6.3-1ubuntu5))
1#include<stdio.h>
#include<iostream>
using namespace std;
//使用一个结构提表示一个日期,防止函数的参数过多。
//若是使用6个变量,参数就是6个。
bool invalidInput =
false;
typedef struct
{
int year;
int month;
int day;
}date;
const int a[][13]= {
-1,31,28,31,30,31,30,31,31,30,31,30,31,
-1,31,29,31,30,31,30,31,31,30,31,30,31
};
inline void
swap_int(int& a, int&
b)
{
a
= a + b;
b
= a - b;
a
= a - b;
}
inline void swap(date&
a, date& b)
{
swap_int(a.year,b.year);
swap_int(a.month,b.month);
swap_int(a.day,b.day);
}
inline bool isLeap(int
year)
{
if(year@0 == 0 ||(year%4 == 0 &&
year0!=0))
return true;
return false;
}
int daysInYear(const
date& _date)
{
int tmp = 0;
int index = 0;
if(isLeap(_date.year))
index = 1;
for(int i = 1; i < _date.month;
i++)
{
cout <<
"tmp: " << tmp
<< endl;
tmp += a[index][i];
}
cout << "daysInYear: "
<< _date.year
<< _date.month
<< _date.day
<< endl;
cout << tmp + _date.day
<< endl;
return tmp + _date.day;
}
int restDaysInYear(const
date& _date)
{
cout << "restDaysInyear: _date"
<< _date.year
<< _date.month
<< _date.day
<< endl;
cout << daysInYear(_date)
<< endl;
if(isLeap(_date.year))
return 366 -
daysInYear(_date);
return 365 - daysInYear(_date);
}
int daysBetweenYear(
int& year1, int&
year2)
{
if(year1 < year2)
{
year1 = year1 + year2;
year2 = year1 - year1;
year1 = year1 - year2;
}
cout << "year1: "
<< year1
<< endl;
cout << "year2: "
<< year2
<< endl;
int day = 0;
for(int i = year2 + 1; i < year1;
i++)
if(isLeap(i))
day += 366;
else
day += 365;
cout << "daysBetweenYear: day= "
<< day
<< endl;
return day;
}
int calculateDays( date&
first,date& second)
{
//判断初始条件的合法性
if(first.year <= 0 || second.year <=
0 || first.month <= 0 || first.month
> 12
|| second.month
<= 0|| second.month > 12 || first.day
<= 0|| first.day
>31
|| second.day
<= 0|| second.day >
31)
{
invalidInput = true;
return -1;
}
int minus = 1;
if(first.year == second.year &&
first.month == second.month)
return first.day -
second.day;
else if(first.year == second.year)
{
int day1 =
daysInYear(first);
int day2 =
daysInYear(second);//dayInyear这个函数计算这个日期是当年的第几天。
return day1 - day2;
}
else//此时年也是不同的,在这里因为我会遍历年,所以要分清两个日期的年份谁大谁小
{
if(first.year
< second.year)
{
swap(first,second);
minus = -1;
}
int day1 =
restDaysInYear(second);
int day2 =
daysInYear(first);
int day3 =
daysBetweenYear(first.year,second.year);//此时的first中的年大于second中的。
return (day1 + day2 +
day3)*minus;
}
}
int main()
{
date first = {2000,1,1};
date second= {2000,12,31};
//
scanf("%d%d%d",&first.year,&first.year,&first.year);
//
scanf("%d%d%d",&second.year,&second.year,&second.year);
cout << calculateDays(first,second)
<< endl;
return 0;
}
1第二种:
#include<iostream>
using namespace
std;
const int a[][13] = {
-1,31,28,31,30,31,30,31,31,30,31,30,31,
-1,31,29,31,30,31,30,31,31,30,31,30,31
};
typedef struct
{
int year;
int month;
int day;
}date;
bool isLeap(int year)
{
if(year@0==0 || (year%4==0
&& year0!=0))
return true;
return false;
}
int daysInYear(date&
_date)
{
int index = 0;
int tmp = 0;
if(isLeap(_date.year))
index = 1;
for(int i = 1; i < _date.month;
i++)
{
tmp += a[index][i];
}
return tmp + _date.day;
}
int
calculateDays(date& _date)
{
//这个方法是和一个基点比较,和1年1月1日比较
//计算当前的年份之前,有多少个润年,比如计算的日期是2001 1
20,就是计算(2001-1)和1之间有多少个润年,2001不考虑,因为2001还没有过完。
int numsOfLeapYears = (_date.year-1)/4 -
(_date.year-1)/100 + (_date.year-1)/400;
int daysOfYears = 366*numsOfLeapYears +
365*(_date.year-1-numsOfLeapYears);//省去了循环判断润年或非润年
int daysOfMonthAndDays =
daysInYear(_date);//加上2001年 当年过去的天数
return daysOfMonthAndDays + daysOfYears;
}
int main()
{
date first = {2013,4,24};
date second = {1988,12,19};
cout <<
calculateDays(first) - calculateDays(second);
return 0;
}