力扣刷题记录

89 阅读3分钟
力扣链接练习次数解题方法数量
无重复字符的最长子串1
LRU 缓存2
5. 最长回文子串1
1. 两数之和2
15. 三数之和2
206. 反转链表1

3. 无重复字符的最长子串

var lengthOfLongestSubstring = function (s) {
    let map = new Map();
    let maxLen = 0;
    let left = 0;
    for (let i = 0; i < s.length; i++) {
        if (map.has(s[i]) && map.get(s[i]) >= left) {  //不要遗漏重复字符索引始终大于等于左指针
            left = map.get(s[i]) + 1;
        }
        map.set(s[i], i);
        maxLen = Math.max(maxLen, i - left + 1);
    }
    return maxLen
};

146. LRU 缓存

//双向链表实现获取缓存中最久未使用的节点的值,哈希表实现查找O(1)
//节点
class ListNode {
    constructor(key, value) {
        this.key = key;
        this.value = value;
        this.prev = null;
        this.next = null;
    }
}
//实现缓存的类
class LRUCache {
    constructor(capacity) {
        this.capacity = capacity;
        this.hash = {};
        this.count = 0;
        this.dummyHead = new ListNode()
        this.dummyTail = new ListNode()
        this.dummyHead.next = this.dummyTail;
        this.dummyTail.prev = this.dummyHead;
    }

    //获取节点值,不存在返回-1,存在返回节点值并且删除把节点,再把改节点添加到链表头部
    get(key) {
        let node = this.hash[key];
        if (!node) return -1;
        this.deleteNode(node);
        this.addToHead(node);
        return node.value;
    }

    //添加节点值,要添加的节点如果已经存在,更新value,以及删除该节点,挪动到链表头部;
    //如果不存在,判断容量是否满,未满则添加新节点到hash表,以及添加到链表头部,更新节点数量
    put(key, value) {
        let node = this.hash[key];
        if (node) {
            node.value = value;
            this.deleteNode(node);
            this.addToHead(node);
        } else {
            if (this.count == this.capacity) {
                this.deleteTailNode();
            }
            let newNode = new ListNode(key, value);
            this.hash[key] = newNode;
            this.count++;
            this.addToHead(newNode)
        }
    }

    //下面是节点工具函数
    //1.删除双向链表中的节点
    deleteNode(node) {
        let temp1 = node.prev;
        let temp2 = node.next;
        temp1.next = temp2;
        temp2.prev = temp1;
    }

    //2.添加节点到链表头部
    addToHead(node) {
        let temp = this.dummyHead.next;
        this.dummyHead.next = node;
        node.prev = this.dummyHead;
        node.next = temp;
        temp.prev = node
    }
    //3.删除最久未使用的节点
    deleteTailNode() {
        let tail = this.dummyTail.prev;
        this.deleteNode(tail);
        delete this.hash[tail.key];
        this.count--;
    }

}
//使用 Map 类型迭代顺序与生成顺序一致的特性完成 key 新旧的标记,简化了上述
var LRUCache = function(capacity) {
    this.limit = capacity;
    this.cache = new Map();
};

LRUCache.prototype.get = function(key) {
    let tmp;
    if(this.cache.has(key)){
        tmp = this.cache.get(key);
        this.cache.delete(key);
        this.cache.set(key,tmp);
    }
    return tmp ?? -1;
};

LRUCache.prototype.put = function(key, value) {
    if(this.cache.has(key)){
        this.cache.delete(key);
    }
    this.cache.set(key,value);
    if(this.cache.size > this.limit){
        this.cache.delete(this.cache.keys().next().value)
    }
};

5. 最长回文子串

//中心扩展方法
var longestPalindrome = function(s) {
        if (s.length<2){
            return s
        }
        let res = ''
        for (let i = 0; i < s.length; i++) {
            // 回文子串长度是奇数
            helper(i, i)
            // 回文子串长度是偶数
            helper(i, i + 1) 
        }

        function helper(m, n) {
            while (m >= 0 && n < s.length && s[m] == s[n]) {
                m--
                n++
            }
            // 注意此处m,n的值循环完后  是恰好不满足循环条件的时刻
            // 此时m到n的距离为n-m+1,但是mn两个边界不能取 所以应该取m+1到n-1的区间  长度是n-m-1
            if (n - m - 1 > res.length) {
                // slice也要取[m+1,n-1]这个区间 
                res = s.slice(m + 1, n)
            }
        }
        return res
};

1. 两数之和

var twoSum = function (nums, target) {
    let map = new Map()
    for (let i = 0; i < nums.length; i++) {
        if (map.has(target - nums[i])) {
            let num = map.get(target - nums[i])
            return [num,i]
        } else {
            map.set(nums[i], i)
        }
    }
    return [];
};
//暴力枚举
var twoSum = function(nums, target) {
    for(let i=0;i<nums.length;i++){
        for(let j=i+1;j<nums.length;j++){
            if(nums[i]+nums[j] == target){
                return [i,j]
            }
        }
    }
};

15. 三数之和

//  排序 + 双指针 + 三处去重
var threeSum = function (nums) {
    let res = []
    nums.sort((a, b) => a - b);
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] > 0) break;  //排序后如果当前数字大于0,后面都大于0,直接返回结果
        if (i > 0 && nums[i] === nums[i - 1]) continue;//固定指针i跳出重复循环
        let left = i + 1;
        let right = nums.length - 1;
        while (left < right) {
            //三个指针,固定指针i不变,左指针向右跑,右指针向左跑
            //分三种情况:和等于0(保存结果数组、左右指针同时走一步、去除左右指针重复的),和大于0(右指针往左跑一步),和小于0(左指针往右跑一步)
            if (nums[i] + nums[left] + nums[right] === 0) {
                res.push([nums[i], nums[left], nums[right]])
                while (left < right && nums[left] === nums[left + 1]) left++;
                while (left < right && nums[right] === nums[right - 1]) right--;
                left++;
                right--;
            } else if (nums[i] + nums[left] + nums[right] > 0) {
                right--;
            } else {
                left++;
            }

        }
    }
    return res;
};

206. 反转链表

var reverseList = function (head) {
    let cur = head;
    let prev = null;
    while (cur) {
        let nextNode = cur.next;  //先存cur.next再断
        cur.next = prev;
        prev = cur;
        cur = nextNode;
    }
    return prev;
};