算法——大顶堆、排序

112 阅读1分钟

692. 前K个高频单词

image.png

【代码】

/**
 * @param {string[]} words
 * @param {number} k
 * @return {string[]}
 */
 var topKFrequent = function(words, k) {
  let countMap = new Map()
  for (let i = words.length-1; i >=0; i--){
    countMap.set(words[i], (countMap.get(words[i]) || 0) + 1)
  }

  let res = Array.from(countMap.keys())
  res.sort((a, b) => {
    // 两个词出现频率相同是,需要按照字母顺序排序
    return countMap.get(a) === countMap.get(b) ?  a.localeCompare(b) : countMap.get(b) - countMap.get(a)
  })
  return res.slice(0,k)
};

215. 数组中的第K个最大元素

image.png 【代码】 方法一:排序

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findKthLargest = function(nums, k) {
    // 排序 方法很多,写个最基本的(效率较低,还没sort快)
    for(let i = 0; i<nums.length;i++){
        for(let j = i+1;j<nums.length;j++){
            if(nums[i]>nums[j]){
                [nums[i], nums[j]] = [nums[j], nums[i]]
            }
        }
    }


    while(k-1>0){
        nums.pop()
        k--
    }
    return nums.pop()
};

方法二:大顶堆

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
 var findKthLargest = function(nums, k) {
  let arr = []
  for(let i  = 0; i< nums.length; i++){
      push(arr, nums[i])
  }
  while(k-1>0){
      pop(arr)
      k--
  }
  console.log(arr)
  return peek(arr)
};


// 交换位置
function swap(heat, index1, index2) {
    [heat[index1], heat[index2]] = [heat[index2], heat[index1]]
}

// 比较两个节点大小
function compare(node1, node2) {
    const diff = node1 - node2
    return diff
}

// 扔一个数据进去,调整成最大堆
function push(heat = [], node) {
    const index = heat.length
    heat.push(node)
    siftUp(heat, node, index)
}

// 1.弹出顶层数据
// 2.调整成最大堆
function pop(heat) {
    const first = heat[0]
    if (first !== undefined) {
    const last = heat.pop()
    if (last !== first) {
        heat[0] = last
        siftDown(heat, last, 0)
    }
    } else {
    return null
    }
}

function siftDown(heat, node, i) {
    let index = i
    let len = heat.length
    while (index < len) {
    const leftIndex = (index + 1) * 2 - 1
    const left = heat[leftIndex]

    const rightIndex = (index + 1) * 2 
    const right = heat[rightIndex]

    if (left !== undefined && compare(left, node) > 0) {
        // 左子节点和根节点相比更大,需要调整

        if (right !== undefined && compare(right, left) > 0) {
        // 右子节点更大
        swap(heat, index, rightIndex)
        index = rightIndex
        } else {
        swap(heat, index, leftIndex)
        index = leftIndex
        }

    } else if (right !== undefined && compare(right, node) > 0) {
        // 右子节点和根节点相比更大,需要调整
        heat[index] = right
        heat[rightIndex] = node
        index = rightIndex
    } else {
        return
    }
    }
}

// 向上筛选
function siftUp(heat, node, index) {
while (true) {
  // 向右移动
  const parentIndex = (index - 1) >>> 1
  const parent = heat[parentIndex]
  if (parent !== undefined && compare(parent, node) < 0) {
    // 父节点比子节点小
    swap(heat, parentIndex, index)
    index = parentIndex
  } else {
    // 父节点比子节点大
    return
  }
}
}

// 获取顶层数据
function peek(heat) {
    const first = heat[0]
    return first === undefined ? null : first
}