首先来了解一下什么是二叉树(Binary tree),它是树形结构的一个重要类型,二叉树的存储结构及其算法都较为简单,二叉树特点是每个结点最多只能有两棵子树,且有左右之分,一个是左侧子节点,一个是右侧子节点;在这里概念性的东西不做过多介绍,大家有兴趣可以私下去了解,直接上题:
如下图:
查找上图二叉树中节点值的和等于固定值的路径,并输出满足条件的所有路径;(例如:节点值的和等于28的路径);
分析: 那明显有两条路径[19,4,5]和[19,8,1],那么它是如何通过代码表达出来呢?大家一看到二叉树这种题,可能由于之前了解的不多,感觉很高端无从下手,脑袋一片空白,首先就自乱阵脚了,那面试的结果就可想而知了,其实二叉树就是一种数据结构,没有那么难,我换一种问法大家就知道了;
var tree={
val:19,
left:{
val:4,
left:{
val:7,
},
right:{
val:5
}
},
right:{
val:8,
left:{
val:1
},
right:{
val:3
}
}
};
查找tree对象中val值相加等于28的路径,并输出满足条件的所有路径;这样问大家是不是就好理解多了。其实二叉树就是一种数据结构,没那么难,下回再遇到相信大家肯定是不会晕头转向了。下面来分析一下这道题
var findPath = function (obj, sum) {
let arrPath = [];
let result = [];//用来存放满足条件的所有路径,最后把这个值return出去
let init = 0;
var isLeaf = function (root) {
//判断是否还有子节点
if (!root.left && !root.right) {
return true
};
return false;
}
function computed(root, init, arrPath, result) {
arrPath = [...arrPath, root["val"]]
init += root["val"];
if (init > sum) {
return false
};
if (init == sum && isLeaf(root)) {
result.push(arrPath)
return;
};
if (root.left) {
computed(root.left, init, arrPath, result);
}
if (root.right) {
computed(root.right, init, arrPath, result);
}
}
computed(obj, init, arrPath, result);
return result;
};
console.log(findPath(objData, 28));
var data={
name: "根",
children: [
{
name: "赵",
children: [{
name: "钱",
children: [{
name: "孙"
}]
}, {
name: "李"
}]
},
{
name: "周",
children: [{
name: "吴"
}]
}
]
}
例题一:
按指定顺序输出值[“根”,“赵”,“钱”,“孙”,“李”,“周”,“吴”];
深度优先遍历:
function find(data){
//深度优先遍历
const arr=[];
function result(data){
data.name&&arr.push(data.name);
while(data.children&&data.children.length>0){
result(data.children.shift());
};
};
result(data);
return arr;
}
console.log(find(data));
例题二:
按指定顺序输出值[“根”,“赵”,“周”,“钱”,“李”,“吴”,“孙”];
function find(data) {
//广度优先遍历
let queue = [],item,total=[];
function result(data) {
if (data.children && data.children.length > 0) {
queue= [...queue, ...data.children];
}
data.name&&total.push(data.name);
while(queue.length!=0){
item=queue.shift();
total.push(item.name);
item.children?queue=[...queue,...item.children]:"";
}
};
result(data);
return total;
}
console.log(find(data));
1.概念
一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f (n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
本次只介绍时间复杂度为O(1)、 O(n)、O(n²)、 O(log(n));
1.1 O(1)
function total(num){
return ++num
}
上述函数的时间复杂度为O(1)(常数);
1.2 O(n)
function fn(arr,item){
for(i=0;i
最坏情况下,假如数组有10个元素,那就是搜索10次,有100个元素就是搜索100次。可以得出fn的时间复杂度O(n),n是输入的数组的长度
1.3 O(n²)
function bubbleSort(arr) {
var max = arr.length - 1;
for (var i = 0; i < max; i++) {
for (var j = 0; j < max - i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
这是比较常见的数组冒泡排序;它时间复杂度就是O(n²);
如果用长度为10的数组,开销就是100 (10²) ,如果用长度为100的数组,开销就是10000 (100²) 。时间复杂度O(n)的代码只有一层循环,而O(n²)的代码是双层循环嵌套,如果是三层循环嵌套,那时间复杂度就是O(n³);
1.3 O(log(n))
function search(arr,data){ // 二分搜索
var max = arr.length-1,
min = 0;
while(min<=max){
var mid = Math.floor((max+min)/2);
if(arr[mid]data){
max = mid-1;
}else{
return mid;
}
}
return -1;
}
var arr = [0, 3, 6, 4,7,5,6,2,3,56,4];
function find(arr) {
arr=Array.from(new Set(arr)).sort();
if(arr[0]+arr[1]>arr[arr.length-1]){
return false;
}
for (var i = 0,j = arr.length - 1; i < j;) {
if (arr.indexOf(arr[j] - arr[i]) > -1 && (arr[j] - arr[i]) != arr[i]&& (arr[j] - arr[i]) != arr[j]) {
//此处判断的作用是排除6-3=3或者是6-0=6这种情况
return true;
} else if (i+1<j) {
i++;
} else if (j > 2) {
j--;
i=0;
}else{
return false;
}
}
}
console.log(find(arr));
注意:例如这道题其实面试官考察的不是你能不能写出来,而是你写的是不是最优解(时间复杂度),在写代码时尽量不要用循环嵌套解决问题,可以用递归或者其它的方式代替,思路要灵活,在写代码时一定要注意这点!
栈和队列都是线性表,只是限制了插入和删除的位置;
栈:它是一种具有后进先出性质的数据结构,也就是说后存放的先取,先存放的后取。举个简单的例子,就如同我们给手电筒装电池,先放进的电池最后才能取出,最后放进的电池最先取出。只能插入在表尾,删除的时候也只能在表尾,就类似于我们操作数组只能使用pop和push方法去解决一些问题。
队列:FIFO(first in first out)它是一种具有先进先出性质的数据结构,也就是说先存放的先取,后存放的后取。举个简单的例子,就如同我们排队买票,必须按照顺序来,不能插队。只能对表的头部进行删除,尾部进行添加,就类似于我们操作数组只能使用shift和push方法去解决一些问题;
例题:
实现用一个栈实现另一个栈的排序(一个栈中元素类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个辅助栈。
除此之外,可以申请新的变量,但不能申请额外的数据结构。如何完成排序?)
let arr=[6,8,5,7,4,2,9]
function stackSort(arr){
let stack=[],cur,item;
while(arr.length){
cur=arr.pop();
if(!stack.length){
stack.push(cur);
}else if(cur<stack[stack.length-1]){
stack.push(cur);
}else if(cur>stack[stack.length-1]){
while(stack.length){
item=stack.pop();
if(cur<item){
stack.push(item)
stack.push(cur);
break;
}else if(cur>item){
arr.push(item);
if(!stack.length){
stack.push(cur);
break;
}
}
}
}
}
return stack;
}
console.log(stackSort(arr));
思路:
什么是斐波那契数列?
1,1,2,3,5,8,13,21,…
这个数列从第3项开始,每一项都等于前两项之和。
function fibonacci(n){
return (n<=2)?1:fibonacci(n-1)+fibonacci(n-2)
}
function fibonacci(n){
let [a,b]=[0,1];
for(let i=0;i<n;i++){
[a,b]=[b,a+b];//起到了var t = a + b;a = b;b = t;的作用
}
return b
}
function fn2(n){
return Array(n).fill().reduce(([a,b],_)=>{
return [b,a+b]
},[0,1])[1]
}
对之前前端面试的数据结构与算法题做出的一些总结,可能有一些瑕疵,但希望能对正在找工作的您起到一些帮助作用,如果大家看完之后感觉写的还可以,麻烦您帮忙点个赞+评论一下,谢谢!最后预祝大家工作顺利!