解决那100道前端面试题~

185 阅读3分钟

关联:2020最新:100道有答案的前端面试题

前言:因为题目链接的解法,不一定正确,以下是我测试通过的解法,关联leetcode。

1. 写一个 mySetInterVal(fn, a, b),每次间隔 a,a+b,a+2b,...,a+nb 的时间,然后写一个 myClear,停止上面的 mySetInterVal

解法:

function produce(fn, a, b) {
  var mySetInterVal, myClear; // 函数
  var num = 0; // 起始值
  var timer;

  mySetInterVal = () => {
    timer = setTimeout(() => {
      fn();
      num++;
      mySetInterVal();
    }, a + num * b);
  };

  myClear = () => {
    clearTimeout(timer);
    num = 0;
  };

  return [mySetInterVal, myClear];
}

var loop = () => {
  console.log('loop called');
};

var [mySetInterVal, myClear] = produce(loop, 1000, 2000);

mySetInterVal();
myClear();

不需要用类生成,直接导出两个方法,我觉得更匹配原题的需求。

2. 合并二维有序数组成一维有序数组,归并排序的思路

// 合并两个有序数组
function mergeArray(arr1, arr2) {
  let res = [];

  while (arr1.length && arr2.length) {
    const item1 = arr1[0];
    const item2 = arr2[0];

    if (item1 < item2) {
      res.push(arr1.shift());
    } else {
      res.push(arr2.shift());
    }
  }

  // 一个数组已经合并完,剩余一个数组没合并完
  res = res.concat(arr1).concat(arr2);

  return res;
}

// var arr1 = [1, 2, 4];
// var arr2 = [3, 5, 6];

// var res = mergeArray(arr1, arr2);
// console.log('%c⧭', 'color: #aa00ff', res);

// 二维有序数组 合并
var twoDArray = [
  [1, 2, 4],
  [0, 5, 6],
  [3, 7, 8],
];
// 合并
function mergeTwoDArray(twoDArray) {
  if (twoDArray.length === 1) {
    return twoDArray[0];
  }

  const mid = Math.floor(twoDArray.length / 2);

  // 先分 递归到长度为1的数组
  const leftArrays = twoDArray.slice(0, mid);
  const leftArray = mergeTwoDArray(leftArrays);

  const rightArrays = twoDArray.slice(mid, twoDArray.length);
  const rightArray = mergeTwoDArray(rightArrays);

  // 后归 两个一维有序数组进行合并 合并成一个有序数组
  const mergeArr = mergeArray(leftArray, rightArray);

  return mergeArr;
}

var res = mergeTwoDArray(twoDArray);
console.log('%c⧭', 'color: #e50000', res);

// 一维乱序数组 合并
var disorderedArray = [3, 1, 2, 7, 8, 9];

function mergeDisorderedArray(arr) {
  if (arr.length === 1) {
    return arr;
  }

  const mid = Math.floor(arr.length / 2);

  const leftArrays = arr.slice(0, mid);
  const leftArray = mergeDisorderedArray(leftArrays);

  const rightArrays = arr.slice(mid, arr.length);
  const rightArray = mergeDisorderedArray(rightArrays);

  const mergeArr = mergeArray(leftArray, rightArray);

  return mergeArr;
}

var res1 = mergeDisorderedArray(disorderedArray);
console.log('%c⧭', 'color: #ffa640', res1);

3. 多种方式实现斐波那契数列

// 最简单方法 递归(存在重复计算,n较大时影响性能)
function fib(n) {
  if (n < 0) throw new Error('输入的数字不能小于0');

  console.log('%c n = %s', 'color: #807160', n);
  if (n < 2) {
    return n;
  }

  const fib_n_1 = fib(n - 1);
  const fib_n_2 = fib(n - 2);

  return fib_n_1 + fib_n_2;
}

var n = 3;

var res = fib(n);
console.log('%c res = %s', 'color: #731d1d', res);

// 记录fib(n - 1)和fib(n-2) 避免重复计算 从下标2开始向上计算
function fib1(n) {
  if (n < 0) throw new Error('输入的数字不能小于0');

  if (n < 2) {
    return n;
  }

  let f0 = 0;
  let f1 = 1;
  let fn = f0;

  // 从下标为2开始
  let i = 2;

  while (i <= n) {
    fn = f0 + f1;
    f0 = f1;
    f1 = fn;
    i++;
  }

  return fn;
}

var n = 3;
var res1 = fib1(n);
console.log('%c res1 = %s', 'color: #007300', res1);

// 递归计算 n-- 同时fn= f0 + f1增加
function fib2(n) {
  if (n < 0) throw new Error('输入的数字不能小于0');

  if (n < 2) {
    return n;
  }

  function _fib(n, f0, f1) {
    if (n === 0) {
      return f0;
    }
    return arguments.callee(n - 1, f1, f0 + f1);
  }

  return _fib(n, 0, 1);
}

var n = 3;
var res2 = fib2(n);
console.log('%c res2 = %s', 'color: #006dcc', res2);

// 数组方法
function fib3(n) {
  if (n < 0) throw new Error('输入的数字不能小于0');

  if (n < 2) {
    return n;
  }

  const list = [0, 1];

  for (let i = 2; i <= n; i++) {
    list[i] = list[i - 1] + list[i - 2];
  }

  return list[n];
}

var n = 3;
var res3 = fib3(n);
console.log('%c res3 = %s', 'color: #731d6d', res3);
  1. 字符串出现的不重复最长长度
var lengthOfLongestSubstring = function (s) {
  let i = 0; // 左指针
  let j = 0; // 右指针
  let maxLen = 0; // 最大长度

  // 当不重复子字符串 不包含s字符串中j下标的字符
  while (i < s.length) {
    let curStr = ''; // 不重复子字符串

    while (curStr.indexOf(s[j]) === -1 && j < s.length) {
      curStr += s[j];
      j++;
      maxLen = Math.max(maxLen, curStr.length);
    }

    // 找到重复字符
    const repeatChar = s[j];

    // 重复字符在子字符串的下标
    const indexOfCurStr = curStr.indexOf(repeatChar);

    // 重复字符在字符串的下标
    const newI = indexOfCurStr + i;

    i = newI + 1;
    j = i;

    // 判断当前坐标离字符串末尾长度是否小于等于maxLen
    if (s.length - j <= maxLen) {
      break;
    }
  }

  return maxLen;
};

var s = 'abcabcdee';

var res = lengthOfLongestSubstring(s);
console.log('%c res = %s', 'color: #e57373', res);

// 快慢指针
var lengthOfLongestSubstring1 = function (s) {
  if (s.length < 2) {
    return s.length;
  }

  let j = 0;
  let curStr = '';
  let max = 0;

  while (j < s.length) {
    if (curStr.indexOf(s[j]) === -1) {
      // 子字符串添加无重复字符
      curStr += s[j];
      // 比较最大长度
      max = Math.max(max, curStr.length);
    } else {
      // 找到重复字符的后一位下标
      const startIndex = curStr.indexOf(s[j]) + 1;
      // 往后推进一位 且不重复
      curStr = curStr.slice(startIndex) + s[j];
    }
    j++;
  }

  return max;
};

var s = 'abcabcdee';

var res1 = lengthOfLongestSubstring1(s);
console.log('%c res1 = %s', 'color: #e57373', res1);