leetcode 算法题: 有效的括号、最近的请求次数、删除链表中的节点、两个数组的交集

182 阅读2分钟

20. 有效的括号

image.png

解题思路
  • 遇到左括号 入栈,遇到右括号出栈
  • 要保证都是有效的括号(可以正常闭合的括号),要保证出栈的括号和遇到的右括号相同,不同为不合法括号
  • 循环结束,栈为空,为有效括号
  • 使用栈数据结构
/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    // 使用 左括号作为key 右括号作为值。保存对应关系
    const map = new Map()
    map.set('(',')');
    map.set('[',']');
    map.set('{','}');
    
    const stack = [];
    // es6 循环字符串语法 for of
    for(let i of s) {
        // 如果当前循环 是左括号 就入栈
        if(map.has(i)) {
            stack.push(i)
        } else {
            // 不是左括号 一定是右括号, 进行对比出栈操作
            // 使用栈顶元素 对比 比对成功才可以出栈
            const last = stack?.[stack?.length -1];
            // 对比成功 出栈
            if(map.get(last) === i) {
                stack.pop();
            } else {
                // 对比失败  说明括号没有有效闭合  如“(]”
                return false;
            }
        }
    }
    // 栈空, 为有效括号
    return stack.length === 0
};
未使用Map数据结构版
/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    const stack = [];
    for(let i of s) {
        if(['(', '[', '{']?.includes(i)) {
            stack.push(i)
        } else {
            const last = stack?.[stack?.length -1];
            if(last === '(' && i === ')' 
            || last === '[' && i === ']' 
            || last === '{' && i === '}') {
                stack.pop();
            } else {
                return false;
            }
        }
    }    
    return stack.length === 0;
};

933. 最近的请求次数

image.png

解题思路
  • 越早进入的请求,一定过会越早超过 3000 秒,所以使用队列结构进行存储
  • 这里涉及的类,的一些东西,要声明一个变量存储每次的请求
  • 在[t -3000, t] 之内的请求才会被保留
  • 使用队列数据结构
var RecentCounter = function() {
    this.queue = [];
};

/** 
 * @param {number} t
 * @return {number}
 */
RecentCounter.prototype.ping = function(t) {
    // 存入队列中
    this.queue.push(t)
    // [t - 3000, t]
    // 每次有新请求都要把把不在 [t - 3000, t] 区间的请求 shift 掉
    while(this.queue[0] < t - 3000) {
        this.queue.shift();
    }
    // 返回剩下的请求长度
    return this.queue?.length;
};

/**
 * Your RecentCounter object will be instantiated and called as such:
 * var obj = new RecentCounter()
 * var param_1 = obj.ping(t)
 */

237. 删除链表中的节点

image.png

解题思路
  • 无法获取当前节点的上个节点,来让上个节点的next 指向下个节点
  • 我们可以让自己 变成 下个节点,然后在把指针指向下个节点的下个节点
  • 使用链表的数据结构
/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} node
 * @return {void} Do not return anything, modify node in-place instead.
 */
var deleteNode = function(node) {
    // 把下个节点的值拿到,我变成了下个节点
    node.val = node.next.val;
    // 把我的指针指向下个节点的下个节点
    node.next = node.next.next;
};

349. 两个数组的交集

image.png

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersection = function(nums1, nums2) {
    // 使用 es6 语法 
    const s2 = new Set(nums2);
    const s1 = new Set(nums1)
    return [...s1].filter(item => s2?.has(item));
};
map 数据结构解法
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersection = function(nums1, nums2) {
    const map = new Map();
    // 把数组1 的数组存入map
    nums1?.forEach(item => {
        if(!map.has(item)) {
            map.set(item,true)
        }
    })
    let res = [];
    //  把数组二 中有的 推入 res, 并删除map防止数据重复
    nums2.forEach(item => {
        if(map.get(item)) {
            map.delete(item);
            res.push(item)
        }
    })
    return res;
};