导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

冷门技能

介绍下深度优先遍历和广度优先遍历,如何实现?

// 1.深度优先遍历的递归写法
function deepTraversal(node) {
  let nodes = [];
  if (node != null) {
    nodes.push[node];
    let children = node.children;
    for (let i = 0; i < children.length; i++) {
      deepTraversal(children[i]);
    }
  }
  return nodes;
}
// 2.深度优先遍历的非递归写法
function deepTraversal(node) {
  let nodes = [];
  if (node != null) {
    let stack = [];
    // 同来存放将来要访问的节点
    stack.push(node);
    while (stack.length !== 0) {
      let item = stack.pop();
      // 正在访问的节点
      nodes.push(item);
      let children = item.children;
      for (let i = children.length - 1; i >= 0; i--) {
        // 将现在访问点的节点的子节点存入stack,供将来访问
        stack.push(children[i]);
      }
    }
  }
  return nodes;
}
// 3.广度优先遍历的递归写法
function wideTraversal(node) {
  let nodes = [], i = 0;
  if (node != null) {
    nodes.push(node);
    wideTraversal(node.nextElementSibling);
    node = nodes[i++];
    wideTraversal(node.firstElementChild);
  }
  return nodes;
}
// 4.广度优先遍历的非递归写法
function wideTraversal(node) {
  let nodes = [], i = 0;
  while (node != null) {
    nodes.push(node);
    node = nodes[i++];
    let children = node.children;
    for (let i = 0; i < children.length; i++) {
      nodes.push(children[i]);
    }
  }
  return nodes;
}

深度遍历广度遍历的区别?

对于算法来说 无非就是时间换空间 空间换时间

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log(m+n))。

示例1: nums1 = [1, 3] nums2 = [2] 中位数是 2.0

示例2: nums1 = [1, 2] nums2 = [3, 4] 中位数是 (2 + 3) / 2 = 2.5

const findMedianSortedArrays = function(nums1, nums2) {
  const lenN1 = nums1.length;
  const lenN2 = nums2.length;
  const median = Math.ceil((lenN1 + lenN2 + 1) / 2);
  const isOddLen = (lenN1 + lenN2) % 2 === 0;
  const result = new Array(median);
  let i = 0; // pointer for nums1
  let j = 0; // pointer for nums2
  for (let k = 0; k < median; k++) {
    if (i < lenN1 && j < lenN2) {
      if (nums1[i] < nums2[j]) {
        result[i + j] = nums1[i++];
      } else {
        result[i + j] = nums2[j++];
      }
    } else if (i < lenN1) {
      result[i + j] = nums1[i++];
    } else if (j < lenN2) {
      result[i + j] = nums2[j++];
    }
  }
  if (isOddLen) {
    return (result[median - 1] + result[median - 2]) / 2;
  } else {
    return result[median - 1];
  }
};

说出几种你能想到的JS 变量交换的方法

方法一:算术运算法

实现原理:

把 a、b 看做数轴上的点,围绕两点间的距离来进行计算。

let a = 8;
let b = 6;

a = b - a;
b = b - a;
a = b + a;

console.log("a:" + a + " ,b:" + b); // 输出 a:6 ,b:8 交换成功

具体过程:

完成交换 !

方法二:借助数组特性交换

实现原理:

借助数组的下标及运算符的优先级实现

let a = 1,
  b = 2;

a = [a, b]; // 让 a 变成数组
b = a[0]; // 先取出 b
a = a[1]; // 再覆盖 a

console.log("a:" + a + " ,b:" + b); // 输出 a:2 ,b:1 完成交换

方法三:位运算

代码实现

let a = 1, // 二进制:0001
  b = 2; // 二进制 0010

a ^= b; // a = a ^ b = 1 ^ 2 = 3
b ^= a; // b = b ^ (a ^ b) = 2 ^ (1 ^ 2) = 1
a ^= b;

console.log("a:" + a + " ,b:" + b); // 输出 a:2 ,b:1 完成交换

实现原理:

方法四:ES6 的解构

用解构的语法特性,一次性解决,简单粗暴 !

let a = 1,
  b = 2;

[a, b] = [b, a];

console.log("a:" + a + " ,b:" + b); // 输出 a:2 ,b:1 交换完成

方法五:借助对象的键值对

实现原理:

把 a 先变成了一个对象,这个对象保存着应该交换后的键值对,最后赋值搞定

let a = 1,
  b = 2;

a = { a: b, b: a };
b = a.b;
a = a.a;

console.log("a:" + a + " ,b:" + b); // 输出 a:2 ,b:1 完成交换