js(83)~451. 根据字符出现频率排序(总结-前k个高频词)

109 阅读2分钟

本题力扣传送门

image.png

这道题我看完首先想到就是大顶堆,跟之前写的 js(81)~[347] 前 K 个高频元素 以及 的js(65)~[692] 前K个高频单词是一样的思路其实,昨天刚写过81篇,所以拿过来继续写,竟然直接改写对了,只不过各项指标都拍后,并且这次把上次es5的写法升级成es6写法.

代码如下.

改造前es5 \

/**
 * @param {string} s
 * @return {string}
 */
var frequencySort = function(s) {
    const  nums = s;
 const map = new Map();
  
  for(const num of nums) {
    map.set(num, (map.get(num) || 0) + 1);
  }
  console.log('map', map)

  // 创建大顶堆
  // 如果是a[1]-b[1] 就是小顶堆
  const priorityQueue = new PriorityQueue((a, b) => b[1] - a[1]);

  // entry 是一个长度为2的数组,0位置存储key,1位置存储value
  for (const entry of map.entries()) {
    priorityQueue.push(entry);
    
  }

    console.log(priorityQueue,'p')
  const ret = [];

  for(let i = priorityQueue.size() - 1; i >= 0; i--) {
    // ret[i] = priorityQueue.pop()[0];
    ret.push(priorityQueue.pop()[0])
  }
  console.log('ret', ret)
  const res = [];
  for(const w of ret){
      for(const word of s){
          if(w === word){
              res.push(word)
          }
      }
  }
    console.log('res->',res)
  return res.join('');
};

// class PriorityQueue {
//     constructor(cmp){
//         this.queue = [];
//         this.compareFn = cmp;
//     }
//     push(item) {
        
//     }
// }

function PriorityQueue(compareFn) {
  this.compareFn = compareFn;
  this.queue = [];
}

// 添加
PriorityQueue.prototype.push = function(item) {
  this.queue.push(item);
  let index = this.queue.length - 1;
  let parent = Math.floor((index - 1) / 2);
  // 上浮 大顶堆
  while(parent >= 0 && this.compare(parent, index) > 0) {
    // 交换
    [this.queue[index], this.queue[parent]] = [this.queue[parent], this.queue[index]];
    index = parent;
    parent = Math.floor((index - 1) / 2);
  }
}

// 获取堆顶元素并移除
PriorityQueue.prototype.pop = function() {
  const ret = this.queue[0];

  // 把最后一个节点移到堆顶
  this.queue[0] = this.queue.pop();

  let index = 0;
  // 左子节点下标,left + 1 就是右子节点下标
  let left = 1;
  let selectedChild = this.compare(left, left + 1) > 0 ? left + 1 : left;

  // 下沉
  while(selectedChild !== undefined && this.compare(index, selectedChild) > 0) {
    // 交换
    [this.queue[index], this.queue[selectedChild]] = [this.queue[selectedChild], this.queue[index]];
    index = selectedChild;
    left = 2 * index + 1;
    selectedChild = this.compare(left, left + 1) > 0 ? left + 1 : left;
  }

  return ret;
}

PriorityQueue.prototype.size = function() {
  return this.queue.length;
}

// 使用传入的 compareFn 比较两个位置的元素
PriorityQueue.prototype.compare = function(index1, index2) {
  if (this.queue[index1] === undefined) {
    return 1;
  }
  if (this.queue[index2] === undefined) {
    return -1;
  }

  return this.compareFn(this.queue[index1], this.queue[index2]);
}


改造后es6/

/**
 * @param {string} s
 * @return {string}
 */
var frequencySort = function(s) {
    const  nums = s;
 const map = new Map();
  
  for(const num of nums) {
    map.set(num, (map.get(num) || 0) + 1);
  }
  console.log('map', map)

  // 创建大顶堆
  // 如果是a[1]-b[1] 就是小顶堆
  const priorityQueue = new PriorityQueue((a, b) => b[1] - a[1]);

  // entry 是一个长度为2的数组,0位置存储key,1位置存储value
  for (const entry of map.entries()) {
    priorityQueue.push(entry);
    
  }

    console.log(priorityQueue,'p')
  const ret = [];

  for(let i = priorityQueue.size() - 1; i >= 0; i--) {
    // ret[i] = priorityQueue.pop()[0];
    ret.push(priorityQueue.pop()[0])
  }
  console.log('ret', ret)
  const res = [];
  for(const w of ret){
      for(const word of s){
          if(w === word){
              res.push(word)
          }
      }
  }
    console.log('res->',res)
  return res.join('');
};

class PriorityQueue {
    constructor(cmp){
        this.queue = [];
        this.compareFn = cmp;
    }
    push(item) {
        this.queue.push(item);
        let index = this.queue.length - 1;
        let parent = Math.floor((index - 1) / 2);
        // 上浮 大顶堆
        while(parent >= 0 && this.compare(parent, index) > 0) {
            // 交换
            [this.queue[index], this.queue[parent]] = [this.queue[parent], this.queue[index]];
            index = parent;
            parent = Math.floor((index - 1) / 2);
        }
    }
    pop() {
        const ret = this.queue[0];

        // 把最后一个节点移到堆顶
        this.queue[0] = this.queue.pop();

        let index = 0;
        // 左子节点下标,left + 1 就是右子节点下标
        let left = 1;
        let selectedChild = this.compare(left, left + 1) > 0 ? left + 1 : left;

        // 下沉
        while(selectedChild !== undefined && this.compare(index, selectedChild) > 0) {
            // 交换
            [this.queue[index], this.queue[selectedChild]] = [this.queue[selectedChild], this.queue[index]];
            index = selectedChild;
            left = 2 * index + 1;
            selectedChild = this.compare(left, left + 1) > 0 ? left + 1 : left;
        }

        return ret;
    }
    size(){
        return this.queue.length;
    }

    compare(index1,index2){
        if (this.queue[index1] === undefined) {
            return 1;
        }
        if (this.queue[index2] === undefined) {
            return -1;
        }

        return this.compareFn(this.queue[index1], this.queue[index2]);
    }

}