前端面试的数据结构与算法

前端面试的数据结构与算法

  • 面试大厂时会问的数据结构与算法
    • 数据结构(二叉树)
      • 1.找出二叉树中节点值的和等于固定值的路径
      • 2.深度优先遍历与广度优先遍历
        • 2-1 深度优先遍历
        • 2-2 广度优先遍历
    • 算法
      • 1.时间复杂度
      • 2.判断数组中是否满足有其中一项等于其它两项之和;
      • 3.栈和队列
      • 4.斐波那契数列
    • 总结

面试大厂时会问的数据结构与算法

数据结构(二叉树)

首先来了解一下什么是二叉树(Binary tree),它是树形结构的一个重要类型,二叉树的存储结构及其算法都较为简单,二叉树特点是每个结点最多只能有两棵子树,且有左右之分,一个是左侧子节点,一个是右侧子节点;在这里概念性的东西不做过多介绍,大家有兴趣可以私下去了解,直接上题:
如下图:
前端面试的数据结构与算法_第1张图片

1.找出二叉树中节点值的和等于固定值的路径

查找上图二叉树中节点值的和等于固定值的路径,并输出满足条件的所有路径;(例如:节点值的和等于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));

最后的输出结果:
前端面试的数据结构与算法_第2张图片

2.深度优先遍历与广度优先遍历

2-1 深度优先遍历

(如下图1-2-3-4-5-6-7顺序遍历)
前端面试的数据结构与算法_第3张图片

 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));

2-2 广度优先遍历

(如下图1-2-3-4-5-6-7顺序遍历)
前端面试的数据结构与算法_第4张图片

例题二:
按指定顺序输出值[“根”,“赵”,“周”,“钱”,“李”,“吴”,“孙”];

 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.时间复杂度

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;
    }

2.判断数组中是否满足有其中一项等于其它两项之和;

    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));

注意:例如这道题其实面试官考察的不是你能不能写出来,而是你写的是不是最优解(时间复杂度),在写代码时尽量不要用循环嵌套解决问题,可以用递归或者其它的方式代替,思路要灵活,在写代码时一定要注意这点!

3.栈和队列

栈和队列都是线性表,只是限制了插入和删除的位置;

:它是一种具有后进先出性质的数据结构,也就是说后存放的先取,先存放的后取。举个简单的例子,就如同我们给手电筒装电池,先放进的电池最后才能取出,最后放进的电池最先取出。只能插入在表尾,删除的时候也只能在表尾,就类似于我们操作数组只能使用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. 遍历给定栈(arr),栈顶出栈(cur=arr.pop()),cur与stack栈顶元素比较
  2. 如果cur小于stack栈顶元素值,那么将cur添加至stack栈顶
  3. 如果cur大于stack栈顶元素值,那么遍历stack栈元素与cur进行比较,如果cur大于stack栈顶元素,那么就把stack栈顶元素重新压入给定栈(arr),直到找到cur小于stack栈顶元素,再把cur压入stack栈;
  4. 直到给定栈arr为空,循环结束;

4.斐波那契数列

什么是斐波那契数列?
1,1,2,3,5,8,13,21,…
这个数列从第3项开始,每一项都等于前两项之和。

  1. 递归实现
   function fibonacci(n){
     
       return (n<=2)?1:fibonacci(n-1)+fibonacci(n-2)
   }
  1. 循环实现
    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
    }
  1. 数组的reduce实现
 function fn2(n){
     
        return Array(n).fill().reduce(([a,b],_)=>{
     
              return [b,a+b]
        },[0,1])[1]
    }

总结

对之前前端面试的数据结构与算法题做出的一些总结,可能有一些瑕疵,但希望能对正在找工作的您起到一些帮助作用,如果大家看完之后感觉写的还可以,麻烦您帮忙点个赞+评论一下,谢谢!最后预祝大家工作顺利!

你可能感兴趣的:(笔记,数据结构,二叉树,算法,栈,javascript)