190 阅读1分钟

const tree = {
  val: 'a',
  children: [
    {
      val: 'b',
      children: [{ val: 'd' }, { val: 'e' }],
    },
    {
      val: 'c',
      children: [{ val: 'f' }, { val: 'g' }],
    },
  ],
}

16c08ea871f0739f_tplv-t2oaga2asx-zoom-in-crop-mark_1304_0_0_0.awebp

深度优先遍历

function dfs(tree) {
  const { val, children } = tree
  console.log(val)
  children && children.forEach(dfs)
}

// a, b, d, e, c, f, g

广度优先遍历

function bfs(tree) {
  const queue = [tree]
  while (queue.length) {
    const { val, children } = queue.shift()
    console.log(val)
    children && queue.push(...children)
  }
}

// a, b, c, d, e, f, g

二叉树

const tree = {
  val: 1,
  left: {
    val: 2,
    left: { val: 4 },
    right: { val: 5 },
  },
  right: {
    val: 3,
    left: { val: 6 },
    right: { val: 7 },
  },
}

前序遍历

preOrder.png

// 递归
function preOrder(root) {
  if (!root) return
  console.log(root.val)
  preOrder(root.left)
  preOrder(root.right)
}

// 迭代
function preOrder(root) {
  if (!root) return
  const stack = [root]
  while (stack.length) {
    const { val, left, right } = stack.pop()
    console.log(val)
    right && stack.push(right)
    left && stack.push(left)
  }
}

// 1, 2, 4, 5, 3, 6, 7

中序遍历

inOrder.png

// 递归
function inOrder(root) {
  if (!root) return
  inOrder(root.left)
  console.log(root.val)
  inOrder(root.right)
}

// 迭代
function inOrder(root) {
  if (!root) return
  const stack = []
  let p = root
  while (stack.length || p) {
    // priority all left
    while (p) {
      stack.push(p)
      p = p.left
    }
    // output
    const { val, right } = stack.pop()
    console.log(val)
    // right
    p = right
  }
}

// 4, 2, 5, 1, 6, 3, 7

后序遍历

postOrder.png

// 递归
function postOrder(root) {
  if (!root) return
  postOrder(root.left)
  postOrder(root.right)
  console.log(root.val)
}

// 迭代
function postOrder(root) {
  if (!root) return
  const output = []
  const stack = [root]
  while (stack.length) {
    const { val, left, right } = stack.pop()
    output.push(val)
    left && stack.push(left)
    right && stack.push(right)
  }
  // reverse order output
  while (output.length) {
    console.log(output.pop())
  }
}

// 4, 5, 2, 6, 7, 3, 1

leetcode 真题

  • 104
  • 111
  • 102
  • 94
  • 112

ff500aea0c404a6687bb87015456ba82_tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.awebp

class MinHeap {
  heap = []

  insert(val) {
    this.heap.push(val)
    this.shiftUp(this.heap.length - 1)
  }

  /**
   * 上移
   */
  shiftUp(index) {
    // 堆顶
    if (index === 0) return
    const parentIndex = this.getParentIndex(index)
    // 父节点 > 子节点
    if (this.heap[parentIndex] > this.heap[index]) {
      this.swap(parentIndex, index)
      this.shiftUp(parentIndex) // 继续上移
    }
  }

  /**
   * delete head
   */
  pop() {
    // 数组尾部替换堆顶(直接删除会破坏堆结构)
    this.heap[0] = this.heap.pop()
    this.shiftDown(0)
  }

  shiftDown(index) {
    const leftIndex = this.getLeftIndex(index)
    const rightIndex = this.getRightIndex(index)
    // 左节点 < 父节点
    // 向下降位
    if (this.heap[leftIndex] < this.heap[index]) {
      this.swap(index, leftIndex)
      this.shiftDown(leftIndex)
    }
    // 此时堆顶为左侧最小值
    // 判断堆顶是否小于右侧的值
    if (this.heap[rightIndex] < this.heap[index]) {
      this.swap(index, rightIndex)
      this.shiftDown(rightIndex)
    }
  }

  swap(i1, i2) {
    const temp = this.heap[i1]
    this.heap[i1] = this.heap[i2]
    this.heap[i2] = temp
  }

  // eslint-disable-next-line no-bitwise
  getParentIndex = index => (index - 1) >> 1 // Math.floor((i - 1) / 2)

  getLeftIndex = index => index * 2 + 1

  getRightIndex = index => index * 2 + 2

  /** 堆顶 */
  peek = () => this.heap[0]

  size = () => this.heap.length
}

测试

const heap = new MinHeap()
heap.insert(3)
heap.insert(2)
heap.insert(1)
heap.insert(8)
heap.insert(9)
heap.insert(4)
heap.insert(5)
heap.insert(6)
heap.pop()
heap.pop()

leetcode

  • 215
  • 347
  • 23