Leetcode 150.逆波兰表达式求值

题目:150.逆波兰表达式求值

初始思路

和括号的匹配有些像,不过不是相等了,而是在栈顶遇到符号的时候进行运算。

代码

  1. var evalRPN = function (tokens) {
  2. // 用map存下每个运算符
  3. const map = new Map([
  4. ['+', (a, b) => parseInt(a) + parseInt(b)],
  5. ['-', (a, b) => a - b],
  6. ['*', (a, b) => a * b],
  7. ['/', (a, b) => parseInt((a / b)) | 0]
  8. ])
  9. let stack = []
  10. for (const i of tokens) {
  11. // 如果tokens中这个字符在map中,即是字符,就进行运算
  12. if (map.has(i)) {
  13. let fn = map.get(i)
  14. let a = stack.pop()
  15. let b = stack.pop()
  16. // 将运算出来的结果再放入
  17. let res = fn(b, a)
  18. stack.push(res)
  19. } else {
  20. // 如果是数字就入栈
  21. stack.push(i)
  22. }
  23. }
  24. return stack[0]
  25. };

感想

  1. 使用map存下运算符,简洁方便。
  2. 在弹出数字的时候,要注意第一下弹出的应该是减数或者是除数,第二次弹出的才是被减数和被除数。
  3. 加法运算要转换,不然会当成字符串拼接

Leetcode 239.滑动窗口最大值

题目:239.滑动窗口最大值 讲解:https://www.bilibili.com/video/BV1XS4y1p7qj/

初始思路

困难题,尽力而为。。。

代码

  1. var maxSlidingWindow = function (nums, k) {
  2. // 自定义一个单调队列
  3. class MonoQueue {
  4. constructor() {
  5. this.queue = []
  6. }
  7. // 如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
  8. enqueue (value) {
  9. let back = this.queue[this.queue.length - 1]
  10. while (back !== undefined && back < value) {
  11. this.queue.pop()
  12. back = this.queue[this.queue.length - 1]
  13. }
  14. this.queue.push(value)
  15. }
  16. // 如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
  17. dequeue (value) {
  18. let front = this.front()
  19. if (front === value) {
  20. this.queue.shift()
  21. }
  22. }
  23. // 返回队列最前端的元素
  24. front () {
  25. return this.queue[0]
  26. }
  27. }
  28. let q = new MonoQueue()
  29. let i = 0, j = 0
  30. let res = []
  31. while (j < k) {
  32. // 先把滑动窗口内的元素加入单调队列中,按照enqueue的逻辑进行过滤
  33. q.enqueue(nums[j++])
  34. }
  35. res.push(q.front())
  36. while (j < nums.length) {
  37. q.enqueue(nums[j])
  38. q.dequeue(nums[i])
  39. res.push(q.front())
  40. i++
  41. j++
  42. }
  43. return res
  44. };

感想

  1. 单调队列的思路看懂了,但是代码还是不是很明白。

Leetcode 347.前 K 个高频元素

题目:347.前 K 个高频元素

初始思路

topK问题,没什么头绪

代码

  1. var topKFrequent = function (nums, k) {
  2. // 法一:哈希表+sort
  3. let map = new Map()
  4. for (let num of nums) {
  5. //初始化出现次数为1,之后累加
  6. map.set(num, map.has(num) ? map.get(num) + 1 : 1)
  7. }
  8. if (k === map.size) {
  9. //k如果等于map.size,直接返回全部key
  10. return [...map.keys()]
  11. }
  12. let arr = Array.from(map).sort((a, b) => {
  13. //从大到小排序
  14. return b[1] - a[1]
  15. })
  16. return arr.slice(0, k).map(n => n[0])//截取前k个key
  17. };
  18. var topKFrequent = function (nums, k) {
  19. //法二:哈希表+桶排序
  20. let map = new Map();
  21. for (let num of nums) {
  22. //初始化出现次数为1,之后累加
  23. map.set(num, map.has(num) ? map.get(num) + 1 : 1);
  24. }
  25. if (k === map.size) {
  26. //k如果等于map.size,直接返回全部key
  27. return [...map.keys()];
  28. }
  29. const bucketSort = () => {
  30. let arr = [];
  31. let res = [];
  32. map.forEach((value, key) => {
  33. //arr[i]存放频率为i的key数组
  34. if (!arr[value]) arr[value] = [key];
  35. else arr[value].push(key);
  36. });
  37. for (let i = arr.length - 1; i >= 0 && res.length < k; i--) {
  38. if (arr[i]) {
  39. //将数组转换为用逗号分割的参数序列
  40. res.push(...arr[i]);
  41. }
  42. }
  43. return res;
  44. }
  45. return bucketSort();
  46. };

感想

  1. 题解:https://leetcode.cn/problems/top-k-frequent-elements/solution/by-confident-coldenbfp-w28l/
    方法一: 将哈希表转成数组,用sort方法排序再截取前k个key
    方法二: 桶排序,将频率一致的放在同一个桶里,数组下标i放置频率为i的key,最后倒序取出k个key
    sort时间复杂度为为O(nlogn),不符合题意,第二种最好的时间复杂度接近O(n)
  2. 代码随想录是自己定义了堆的结构