leetcode 刷题记录 day13

239. 滑动窗口最大值
思路】先构造一个单调队列,队列里单调递增或者单调递减。因为是求最大值,所以队列里没有必要维护所有元素,只需要确保队列开头第一个元素是最大值即可。新加进来的元素如果比末尾元素小就 pop 末尾元素直到最大值为第一个元素。如果等于开头第一个元素就删除开头第一个元素。
疑问】为什么在 class 类里写,自己用函数写就会死循环。至今还疑问!

var maxSlidingWindow = function(nums, k) {
  class MonoQueue {
        queue;
        constructor() {
            this.queue = [];
        }
        enqueue(value) {
            let back = this.queue[this.queue.length - 1];
            while (back !== undefined && back < value) {
                this.queue.pop();
                back = this.queue[this.queue.length - 1];
            }
            this.queue.push(value);
        }
        dequeue(value) {
            let front = this.front();
            if (front === value) {
                this.queue.shift();
            }
        }
        front() {
            return this.queue[0];
        }
    }
    let helperQueue = new MonoQueue();
    let i = 0, j = 0;
    let resArr = [];
    while (j < k) {
        helperQueue.enqueue(nums[j++]);
    }
    resArr.push(helperQueue.front());
    while (j < nums.length) {
        helperQueue.enqueue(nums[j]);
        helperQueue.dequeue(nums[i]);
        resArr.push(helperQueue.front());
        i++, j++;
    }
    return resArr;
};

347.前 K 个高频元素

思路】这道题可以用小顶堆的方法来解决,因为每次够了 k 个元素要 pop 时,用大顶堆会 pop 掉最大的元素,所以要用小顶堆,每次pop 掉最小的元素。但 js 没有堆,需要自己构造(自己对自己要求低点,别人构造好我直接拿来用了)。

// js 没有堆 需要自己构造
class Heap {
    constructor(compareFn) {
        this.compareFn = compareFn;
        this.queue = [];
    }

    // 添加
    push(item) {
        // 推入元素
        this.queue.push(item);

        // 上浮
        let index = this.size() - 1; // 记录推入元素下标
        let parent = Math.floor((index - 1) / 2); // 记录父节点下标

        while (parent >= 0 && this.compare(parent, index) > 0) { // 注意compare参数顺序
            [this.queue[index], this.queue[parent]] = [this.queue[parent], this.queue[index]];

            // 更新下标
            index = parent;
            parent = Math.floor((index - 1) / 2);
        }
    }

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

        // 移除堆顶元素 填入最后一个元素
        this.queue[0] = this.queue.pop();

        // 下沉
        let index = 0; // 记录下沉元素下标
        let left = 1; // left 是左子节点下标 left + 1 则是右子节点下标
        let searchChild = this.compare(left, left + 1) > 0 ? left + 1 : left;

        while (searchChild !== undefined && this.compare(index, searchChild) > 0) { // 注意compare参数顺序
            [this.queue[index], this.queue[searchChild]] = [this.queue[searchChild], this.queue[index]];

            // 更新下标
            index = searchChild;
            left = 2 * index + 1;
            searchChild = this.compare(left, left + 1) > 0 ? left + 1 : left;
        }

        return out;
    }

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

    // 使用传入的 compareFn 比较两个位置的元素
    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]);
    }

}

var topKFrequent = function(nums, k) {
  let map = new Map();

  for (let k of nums) {
    map.set(k, (map.get(k) || 0) + 1);
  }

  // 创建小顶堆
  let heap = new Heap((a, b) => a[1] - b[1]);  

  for (const entry of map.entries()) {
    heap.push(entry);

    if (heap.size() > k) {
      heap.pop();
    }
  }

  // 遍历堆,返回结果
  const res = [];
  for (let i = heap.size() - 1; i >= 0; i--){
    res[i] = heap.pop()[0];
  }
  return res;
};
  • 总结栈和队列
    js 没有栈和队列,可以用数组的方法自己实现。无非就是数组进出顺序不一样。

    • js 实现一个栈
    class Stack{
      constructor{
        this.stack = []
      }
    
      // 入栈
      push(item) {
        this.stack.push(item)
      }
    
      // 出栈
      pop() {
      	// 如果栈为空,直接返回 null
      	if (this.stack,length === 0) {
      		return null;
      	}
        this.stack.pop()
      }
    
      // 获取栈长度
      getCount() {
        return this.stack.length
      }
    
      // 查看栈顶元素
      peek() {
        return this.stack[this.getCount() - 1]
      }
    
      // 判断是否为空
      isEmpty() {
        return this.getCount === 0
      }
    }
    
    • 自己实现一个队列
    class Queue{
      constructor() {
        this.queue = []
      }
      
      // 入队
      enQueue(item) {
        return this.queue.push(item)
      }
        
      // 出队
      deQueue() {
      	if (this.stack.length === 0) {
      		return null;
      	}
        return this.queue.shift()
      }
        
      // 获取队头
      getHeader() {
        return this.queue[0]
      }
        
      // 获取队列长度
      getlength() {
        return this.queue.length()
      }
        
      // 判断是否为空
      isEmpty() {
        return this.getlength() === 0
      }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值