又到了每一年的金三銀四招聘旺季,有幸得到了微軟的筆試機會,程序猿們應該都知道,老美的公司都喜歡懟數據結構與算法,微軟確定也不例外,我的以爲考數據結構對每個應聘者都公平,我此次投的是微軟蘇研院,筆試考察的不難,是最最多見的數據結構算法裸題,這裏記錄一下,也給出解法。前端
快排應該是最網紅的題了,從校招到社招,從後端到前端再到移動端,都會問,可是估計能手撕出來的不超過一半,能講清楚思路的估計不超過一半的一半,其實用兩個詞歸納,就是雙指針+遞歸分治,在每一輪遞歸的時候找到每一個基準數排完序後的位置,將小於這個基準數的全部數放到它的左邊,將大於這個基準數的全部數放到它的右邊,而後再分別遞歸它左邊的數組與它右邊的數組。好比說數組[2,3,1,5,6,4]:算法
function quickSort(arr, begin, end) {
//遞歸出口
if(begin >= end)
return;
var l = begin; // 左指針
var r = end; //右指針
var temp = arr[begin]; //基準數,這裏取數組第一個數
//左右指針相遇的時候退出掃描循環
while(l < r) {
//右指針從右向左掃描,碰到第一個小於基準數的時候停住
while(l < r && arr[r] >= temp)
r --;
//左指針從左向右掃描,碰到第一個大於基準數的時候停住
while(l < r && arr[l] <= temp)
l ++;
//交換左右指針所停位置的數
[arr[l], arr[r]] = [arr[r], arr[l]];
}
//最後交換基準數與指針相遇位置的數
[arr[begin], arr[l]] = [arr[l], arr[begin]];
//遞歸處理左右數組
quickSort(arr, begin, l - 1);
quickSort(arr, l + 1, end);
}
var arr = [2,3,4,1,5,6]
quickSort(arr, 0, 5);
console.log(arr)
複製代碼
思考:爲何是右指針先掃而不是左指針先掃呢,你們本身想一想吧哈哈,模擬一下就知道了。後端
上文中我提到了左數組,右數組,還提到了基準數的概念,其中,左數組中的全部值都小於基準數,右數組中的全部值都大於基準數,並且快排仍是個遞歸的過程。我這裏若是作一下類比,若是我把基準數當作是樹根,把左數組當作是根的左孩子,右數組當作是根的右孩子,相信學過數據結構的童鞋都知道了,那不就是一顆BST嗎。哈哈確實如此,其實你會發現BST的中序遍歷出來就是一個有序數組,因此上文中快排的過程就是一個建立二叉搜索樹的過程。數組
二叉查找樹(Binary Search Tree),(又:二叉搜索樹,二叉排序樹)它或者是一棵空樹,或者是具備下列性質的二叉樹: 若它的左子樹不空,則左子樹上全部結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上全部結點的值均大於它的根結點的值; 它的左、右子樹也分別爲二叉排序樹.bash
因此要是問你怎麼建立一顆BST,想必也能信手拈來了吧,廢話不說上代碼:數據結構
function vNode(value) {
this.val = value;
this.left = this.right = null;
}
function createBST(arr) {
var len = arr.length;
if(len < 1)
return;
var l = 0;
var r = len - 1;
var temp = arr[0];
while(l < r) {
while(l < r && arr[r] >= temp)
r --;
while(l < r && arr[l] <= temp)
l ++;
[arr[l], arr[r]] = [arr[r], arr[l]];
}
[arr[0], arr[l]] = [arr[l], arr[0]];
var root = new vNode(arr[l]);
root.left = createBST(arr.slice(0, l));
root.right = createBST(arr.slice(l + 1));
return root;
}
複製代碼
我相信不少人都能寫出二叉樹的遞歸遍歷:遞歸遍歷左子樹,輸出根節點,遞歸遍歷右子樹,三行代碼,完事,可是要問到非遞歸遍歷,估計大多數人就傻眼了,可是人家就要考你不會的啊,非遞歸遍歷其實就是藉助棧來完成:ui
var inorderTraversal = function(root) {
const res = [];
const stack = [];
while(root||stack.length !== 0)
{
while(root)
{
stack.push(root);
root=root.left;
}
if(stack.length)
{
let p=stack[stack.length - 1];
res.push(p.val);
stack.pop();
root = p.right;
}
}
return res;
};
複製代碼
老美的公司,算法關必須過啊。因此,路漫漫其修遠兮,刷題刷題多刷題吧this