又到了每一年的金三银四招聘旺季,有幸得到了微软的笔试机会,程序猿们应该都知道,老美的公司都喜欢怼数据结构与算法,微软确定也不例外,我的以为考数据结构对每个应聘者都公平,我此次投的是微软苏研院,笔试考察的不难,是最最多见的数据结构算法裸题,这里记录一下,也给出解法。前端
快排应该是最网红的题了,从校招到社招,从后端到前端再到移动端,都会问,可是估计能手撕出来的不超过一半,能讲清楚思路的估计不超过一半的一半,其实用两个词归纳,就是双指针+递归分治,在每一轮递归的时候找到每一个基准数排完序后的位置,将小于这个基准数的全部数放到它的左边,将大于这个基准数的全部数放到它的右边,而后再分别递归它左边的数组与它右边的数组。好比说数组[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