那些年的拦路虎们

这段时间被阿里面试了两次,以下是这两次笔试的题目,题目本身不难,奈何实力不足,做题的时候容易怂,所以做得不是很好,最近反思之后,将题目重新做了一遍,答案仅为个人想法,测试用例都过了,但还有一定(是很大很大很大)的进步空间,先记录下来,有空的时候再进行二次复盘。

1.一个小时做出以下三道题

难度:两颗星(题目真的不难,就是当时有点紧张)

  1. 手写防抖(debounce),手写节流(throttle)
function debounce(fn, cb) {
  let timer;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn(args), delay);
  };
}

function throttle() {
  let timer;
  return function (...args) {
    timer = setTimeout(() => {
      fn(args);
      clearTimeout(timer);
    }, delay);
  };
}
  1. 获取嵌套数组深度。

    说明:给定一个带嵌套的数组,实现一个方法可获取嵌套数组的最大深度,

    数组无嵌套子数组,则返回0,有一层嵌套子数组则1,依此类推。

    示例:

    getArrayDeep([]); // 返回 0

    getArrayDeep([[[[]]]]); // 返回 3

    getArrayDeep([0, [2], [2, [3]]]); // 返回 2

// 以下的答案能过这三个案例,但是递归本身还是有问题。。。
function getArrayDeep(arr) {
  let depth = 0;
  if (!arr.length) return 0;
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      depth = Math.max(depth, getArrayDeep(arr[i])) + 1;
    }
  }
  return depth;
}
// PS:理论上凡是可以用递归的地方都能用栈实现,奈何我递归学的不是很好,用栈怎么实现先欠着债,总有一天我会还上的

// 接下来是还债时间,按照上文的递归总算是把对应的栈方法写出来了。。。
// 写完之后三个样例都能通过,但是。。。逻辑上还是错的,比如下面这个样例
//e.g. getArrayDeep([2, 3, [2, 3, 4, [2, 3], [4, 5]]])
function getArrayDeep(arr) {
  let depth = 0;
  let temp = 1;
  if (!arr.length) return 0;
  let stack = [];
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      temp = 1;
      stack.push(...arr[i]);
      while (stack.length) {
        let demo = stack.pop();
        if (Array.isArray(demo)) {
          temp++;
          stack.push(...demo);
        }
      }
    }
    depth = Math.max(temp, depth);
  }
  return depth;
}

分析:栈方法其实就是模仿了递归的过程,从栈方法中很容易发现,上面的解法计算的是每个子数组中的数组数量,当子数组中有多个并列的数组时,问题就会出现(哭嘁嘁😭)

// 重新再来,又欠债了
// 晚上回来之后反思了一下,需要返回的是每个子数组中的最深镶嵌数组,所以需要的其实递归的是数组的Math.max
function getArrayDeep(arr) {
  if (!arr.length) return 0;
  let stack = [];
  let depth = 0;
  for (let i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      stack.push(arr[i]);
    }
  }
  stack = stack.map((item) => Math.max(getArrayDeep(item), depth) + 1);
  return Math.max(...stack);
}

 // 还是老样子,在想着栈的方案,想着想着突然想到了flat方法,咦,不是刚刚好这个问题的反解嘛,于是就有个flat的简洁版方案
function getArrayDeep(arr) {
  let temp = 0;
  if (!arr.length) return 0;
  while (Array.isArray(arr) && arr.some((item) => Array.isArray(item))) {
    temp++;
    arr = arr.flat(1);
  }
  return temp;
}

// 顺便附上自定义flat的代码,本质还是递归
function flat(arr, d = 1) {
  return d > 0
    ? arr.reduce(
        (pre, curr) =>
          pre.concat(Array.isArray(curr) ? flat(curr, d - 1) : curr),
        []
      )
    : arr.slice();
}

感悟:很多问题看着很简单,仔细想想还是有很多值得推敲的地方,思考问题需要有一个全面性,按照这道题而言,最开始的解确实能够得到样例正确解,但并非完全正确,思考后发现第二种方法更加接近答案。还有就是要巧妙利用各种API,大佬们都帮我们封装好了为啥不用~
PS:栈方法先鸽,太复杂了,脑子暂时不够使😭😭😭,有肝出来的有缘人求分享~

  1. 实现一个 normalize 函数,能将输入的特定的字符串转化为特定的结构化数据。

    // 字符串仅由小写字母和[,]组成,且字符串不会包含多余的空格。

    // 示例一: ‘abc’ --> {value: ‘abc’}

    // 示例二:’[abc[bcd[def]]]’ -> {value: ‘abc’, children: {value: ‘bcd’, children: {value: ‘def’}}}

    // 默默吐槽一下当时由于紧张写了arr=arr.splice(0,1)的我,啊,社💩翻车现场,还有在reduce里面把函数中所有的pre都写成了obj的我。。。。。。
    function normalize(str) {
      let arr = str.split("[");
      if (arr.length > 1) {
        arr.splice(0, 1);
      }
      let obj = {};
      const len = arr.length;
      arr.reduce((pre, curr, index) => {
        pre.value = curr.replace(/[^\w]*/g, "");
        // console.log(pre, index);
        if (index !== len - 1) {
          pre.children = {};
          console.log(pre);
          return pre.children;
        }
      }, obj);
    
      return obj;
    }
    
2.20分钟做出以下三道题
  1. 问题:实现 calc 方法,统计各个 tag 出现的次数和对应的 name 值。
    const array = [
    {name: ‘articleA’, tags: [‘javascript’, ‘es6’, ‘css’]},
    {name: ‘articleB’, tags: [‘animation’, ‘transform’, ‘css’]},
    {name: ‘articleC’, tags: [‘javascript’, ‘currying’]}
    ];
    console.log(calc(array, ‘javascript’));
    console.log(calc(array, ‘css’));
    输出数据如下:
    javascript: 2, [articleA, articleC]
    css: 2, [articleA, articleB]

    function calc(arr, tag) {
      if (!arr.length) return `${tag}: 0 []`;
      let count = 0;
      let nameArr = [];
      for (let i = 0; i < arr.length; i++) {
        if (arr[i].tags.includes(tag)) {
          count++;
          nameArr.push(arr[i].name);
        }
      }
      return `${tag}: ${count},[${nameArr}]`;
    }
    
  2. 问题:请编写一个JavaScript函数 parseQueryString,它的用途是把URL参数解析为一个对象
    var url = “https://pd.alipay.com/#/product/productHome?catalogCode=GC&tabKey=GOC&roleType=GOC”
    var paramObj = parseQueryString(url);
    console.log(paramObj.catalogCode, paramObj.tabKey, paramObj.roleType); // GC GOC GOC

    function parseQueryString(url) {
      let [host, param] = url.split("?");
      if (!param) return {};
      let obj = {};
      let arr = param.split("&");
      for (let i = 0; i < arr.length; i++) {
        let [key, value] = arr[i].split("=");
        obj[`${key}`] = value;
      }
      return obj;
    }
    
  3. 问题:实现一个简单的模板渲染
    给定一个模板和一个对象,利用对象中的数据渲染模板,并返回最终结果。
    例如:
    let template = '你好,我们公司是{{company}},我们属于{{group.name}}业务线,我们在招聘各种方向的人才,包括{{group.jobs[0]}}、{{group[“jobs”][1]}}等。

    let obj = {
    group: {
    name: “天猫”,
    jobs: [“前端”, “后端”, “产品”]
    },
    company: ‘阿里巴巴’
    }

    function render(tem, obj) {
      return tem.replace(/\{\{\s*(.+?)\s*\}\}/g, (value, $1) => 	   			new Function(`return this.${$1}`).call(obj);
      );
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值