三本的我面試微軟,微軟包機票酒店早餐到蘇州,實在太棒了
- 2021 年 2 月 17 日
- 筆記
2019蘇州微軟面經
簡介,蘇州微軟,目前已經電話三輪,全過,過了後可以公費去蘇州現場面試。
比國外 Google的面試難度要低一些,或者說,偏重點更不一樣。
微軟你可以只做一道面試題,思路清晰,完整,邊界情況考慮清楚,程式碼寫好就行了。
但是 Google 是需要你在 40 分鐘內,完美答出兩道題目,這就是區別。
另外,蘇州微軟是用中文的,也是容易了一些的原因——因為用英語你確實腦子轉不過來。
第一輪
沒有給出題目,口頭說的,我整理一下:
判斷一個數組是否基本有序,其實就是可否通過一次簡單的交換就滿足有序。
例子:
1, 2, 3, 6, 5, 12是基本有序數組,因為可以交換 6 跟 5, 變成1, 2, 3, 5, 6, 121, 5, 4, 3, 6也是基本有序數組,可以交換 5 跟 33,2, 1, 0就不是基本有序數組了,因為你交換一次數組並不能使此數組有序。
思路不難,仔細分析一下,有序的數組數字關係是這樣: a < b < c < d < e,而基本有序則是:a < b > c > d <e,這樣可能不好看,簡單來說就是那兩個數字在是不滿足x < y的關係的。
可以遍歷此數組,只要有多於一個數字是比兩邊都要大,且有一個數字是比左右兩邊要小的,那就是基本有序數組,其餘的都不是。當然,你也要考慮本來這個數組就是有序的情況。
在面試時寫的程式碼與交流草稿如下,這份程式碼是不能當答案看的,只是讓朋友你們看看怎麼樣的程式碼可以過面試。建議你們自己寫寫可以編譯過的程式碼。
int array
1, 2, 3, 6, 5, 12 true
i
min: 3, miax: 5
1, 5, 4, 3, 6
sub array -> reverse -> true
1, 2, 3, 6, _5,
1, 5, 4, 3, 6
max: 5
min: 3
1 < min < max < least
i,
1, 5, 4, 2, 8, 19, 7, 12
5, 4, 9
min: 2
max: 5
sub array -> sorted?
7
3
i: 2,
1, 2, 3, 8, 7, 6 ,5, 12
bool is_almost_sorted_array(vector<int> a) {
int mem_l;
bool flag = false;
int l_idx = -1, r_idx = -1;
On(m sub_arry)
for(int i=0; i<a.size()-1; i++) {
// sub array
if(a[i] > a[i+1]) {
int mem_l = i;
int sub_min = a[mem_l];
if(mem_l+1 < a.size())
sub_min = a[mem_l+1];
while(i<a.size() && a[i] > a[i+1]) {
if(flag == true) return false;
i++;
}
/* 1, 2, 7, 4, 5, 6, 3, 8 */
/* i: 3, ->,
* i: 6,
* */
int sub_max = a[i-1];
if(l_idx == -1 && i - mem_l == 1) {//only one
l_idx = i-1;
}else if(r_idx == -1 && i - mem_l == 1) {
r_idx = i;
if(a[r_idx] > a[l_idx-1] && a[r_idx] < a[l_idx+1] &&
a[l_idx] > a[r_idx-1] && (r_idx == a.size() || a[l_idx] < a[r_idx+1]))
flag = true;
else
return false;
}else{
flag = true; //Have Changed Once
if(sub_min <= a[mem_l] || i == a.size() || sub_max >= a[i])
return false;
}
}
}
return true;
}
test case:
1, 2, 3 =>
3, 2, 1 =>
i:0, a[0]>a[1], mem_l:0, sub_min: 2, subm: 3
i:1, sub_min: a[2] vs 3, 1 3
i:2,
1 >= 1, 3 >=
面試回饋就是對 邊界情況考慮不周全,可以多加強。(是的,如上的一些判斷語句是跟面試官一起過了一遍才加上的)。
第二輪
第二輪面試官是貼了題目,順道解釋了一下,在這裡鍛煉你們的英語能力,我就不給你們解釋了。
Split a string into sub-strings. Each sub-string should be no longer than the given limit. The input string contains English letters and spaces only.
Do not break a word into two sub strings. Remove all spaces in the beginning or end of every sub string.
Extend: append notation such as " (1 of 12)" and strings are not longer than the limit even after the notation.
Length limit: 39. Input: The quick brown fox jumps over a lazy dogThe quick brown fox jumps over a lazy dogThe quick brown fox jumps over a lazy dogThe quick brown fox jumps over a lazy dogThe quick brown fox jumps over a lazy dogThe quick brown fox jumps over a lazy dogThe quick brown fox jumps over a lazy dogThe quick brown fox jumps over a lazy dogThe quick brown fox jumps over a lazy dog
Result should be:
The quick brown fox jumps (1 of 14)
over a lazy dogThe quick (2 of 14)
brown fox jumps over a lazy (3 of 14)
dogThe quick brown fox jumps (4 of 14)
over a lazy dogThe quick (5 of 14)
brown fox jumps over a lazy (6 of 14)
dogThe quick brown fox jumps (7 of 14)
over a lazy dogThe quick (8 of 14)
brown fox jumps over a lazy (9 of 14)
dogThe quick brown fox jumps (10 of 14)
over a lazy dogThe quick (11 of 14)
brown fox jumps over a lazy (12 of 14)
dogThe quick brown fox jumps (13 of 14)
over a lazy dog (14 of 14)
這題我沒有正確的思路,因為現在我還沒有想出最優解,也沒有在網上找到類似的題目,有看過的同學可以分享一下。難點就是,在插入每行附加資訊的同時,又不能讓這行的字數超出。
我是這樣子做的:
每行先不插入資訊,先正常的換行,換行完畢後,再遞歸去插入資訊——因為插入資訊後會因為行數進位而又需要調整一遍,如 99 變成 100.
我寫出的程式碼如下:
vector<string> split_sub_strings(string input, int limit) {
vector<string> res;
int count = 0;
for(int i=0; i<input.length(); ++i) {
int mem_i = i;
string current_line = "";
while(input[i] != ' ') {
i++;
}
int word_len = i - mem_i;
//可以容納下個詞不
if(res[count].length() + word_len> limit) {
res.push_back(current_line);
count++;
continue;
}else {
current_line += input.splice(mem_i, i);
}
while(input[i] == ' ') {
i++;
}
}
return update_info(res, limit, count);
}
string get_apend_info(int cnt, int sum) {
return "(" + to_string(cnt) + " of " to_string(sum) + ")"
}
string retrieve_back_words(string s) {
st
for(int i=s.length(); s>0; s--) {
}
}
// backwords:
//Len 35 : The quick(1 of 14)
//over a lazy dogThe quick jumps brown fox (2 of 14)
// append back workds
vector<string> update_info(vector<string> list_of_lines, int limit, int sum) {
vector<string> res;
int cnt = 0;
string back_words = "";
for(auto line : list_of_lines) {
string new_line = line + retrieve_back_words(back_words) + get_apend_info(cnt, sum);
if(new_line.length() > limit){
for(int i=line.length(); i>0; i--) {
mem_i = i;
while(line[i] != ' ') {
line--;
}
back_words = back_words + line.splice(mem_i, i) + ' ';
new_line = line.splice(0, i) + get_apend_info(cnt, sum);
if(new_line.length() < limit) {
res.push_back(new_line);
}
}
}
}
if(back_words.length == 0) {
return res;
}else {
sum += 1;
res.push_back(retrieve_back_words(back_words)
return update_info(res, limit, sum);
}
}
第三輪
這輪是純英語面試,美國的友人早晨 7 點打電話來的,對於 9 點起床的我來說,狀態不好。
leetcode 原題 //leetcode.com/problems/min-stack/ ,不過我沒有做過。
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
- push(x) — Push element x onto stack.
- pop() — Removes the element on top of the stack.
- top() — Get the top element.
- getMin() — Retrieve the minimum element in the stack.
Example:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> Returns -3.
minStack.pop();
minStack.top(); --> Returns 0.
minStack.getMin(); --> Returns -2.
開始,或者正常人的想法都是馬上想到用一個成員變數來存這個最小值,push 的時候能做到 O1,但是做 pop 的時候發現,這時候不清楚 pop 出去的是不是最小值以及是不是有多個最小值,這時演算法就不是 O1 了。
想了一下子後,我就想到利用 slice window(滑動窗口)的思想來做,用數組記錄區間值最小值,每次 push 不是比這個數小就不存。
例如: 12,6, 9, 7, 5, 22,29, 1 我會這樣子存: 12, 6,5,1。
-
12 無論如何都是要放的,然後 6 比 12 小,存起來;9,7 都不比 6 小,不需要存——之後只要是 9,7 這兩個值,返回最小值 6 就行。
-
然後 5 比 6 小,存起來;22,29 大於 5,不需要存,然後最小值就是之前存起來那個 5 啦。
-
最後 1 比 5 小,存起來。
簡而言之,就是一個最小值列表,存起來當前區間的最小值。
pop 的時候檢查一下最小值數組是否是要 pop 的值,維護一下就行,push 跟 pop 都是 O1 了
做的時候我用的是數組,面試完後我查了下,發現可以用抽象程度更高的 stack 來代替數組。因為我一直處理的也是數組的最後一位,跟 stack 的行為一模一樣的。



