leetcode 算法题:两数之和、无重复字符的最长子串、最小覆盖子串、两数相加

510 阅读2分钟

1. 两数之和

image.png

解题思路
  • 把 nums 想象成找同伴 两个同伴的和 就是 目标值
  • 可以使用 map 存储 同伴数据
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    const m = new Map();
    for(let i = 0;i <= nums.length - 1; i++) {
        const c = nums[i];
        // 计算目标值
        const find  = target - c;
        if(m.has(find)) {
            // 找到返回 返回目标值下标,和当前值下标
            return [m.get(find),i];
        } else {
            // 把自己存入map 等待其他值查找
            m.set(c, i)
        }
    }
    
};

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

image.png

解题思路
  • 先找出所有的不包含重复字符的子串
  • 找出长度最大的那个子串,返回其长度即可
  • 用双指针维护一个滑动窗口,用来剪切子串
  • 不断移动右指针,遇到重复字符,就把左指针移动到重复字符的下一位
  • 过程中,记录所有窗口的长度,并返回最大值
/**
 * @param {string} s
 * @return {number}
 */
var lengthOfLongestSubstring = function(s) {
    // 指针l
    let l = 0;
    let maxLength = 0;
    // 存储没有字符 值和下标
    let map = new Map()
    for(let r = 0;r < s.length;r++) {
        const val = s[r];
        // 重复值,并且在 指针后面,就把移动到它的下一位
        if(map.has(val) && map.get(val) >= l) {
            l = map.get(val) + 1;
        } 
        maxLength = Math.max(maxLength, r - l + 1) 
        map.set(val,r)
        
    }
    return maxLength;
};

76. 最小覆盖子串

image.png

解题思路
  • 先找出所有的包含T的子串
  • 找出长度最小那个子串,返回即可
  • 用双指针维护一个滑动窗口
  • 移动右指针,找到包含T的子串,移动左指针,尽量减少包含T的子串的长度
  • 循环上述过程,找出包含T的最小子串
/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function(s, t) {
    // 左指针
    let l = 0;
    // 右指针
    let r = 0;
    // 需要查找的数据字典 值 和 对象次数
    let need = new Map();
    for(let i of t) {
        need.set(i, need.has(i) ? need.get(i) + 1 : 1);
    }
    // 对应 字符个数 
    let needType = need.size;
    // 最小的结果
    let res = '';

    while(r < s.length) {
        // 循环右指针
        const c = s[r];
        if(need.has(c)) {
            减少需求的数量
            need.set(c, need.get(c) - 1);
            if(need.get(c) === 0) {
                needType -= 1;
            }
        }
        // 找到需要的子串
        while(needType === 0){
            // 截取找到的字符
            const newRes = s.substring(l,r+1)
            
            // 比较更新 res 更新最小长度的
            if(!res || newRes.length < res.length) {
                res = newRes;
            }
            const c2 = s[l];
            // 发现需要的字符更新 need 这样   就会退出此循环,进入 上层 循环
            if(need.has(c2)) {
                need.set(c2,need.get(c2)  + 1);
                if(need.get(c2) === 1) {
                    needType += 1;
                }
            }
            l++
        }
        r++
    }
    return res;
};

2. 两数相加

image.png

解题思路
  • 模拟相加操作
  • 需要遍历链表
  • 倒序排列
  • 新建一个链表
  • 遍历被相加的两个链表,模拟相加操作,将个位数追加到新链表上,将十位数留到下一位去相加
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {
    const l3 = new ListNode(0);
    // 声明三个指针
    let p1 = l1;
    let p2 = l2;
    let p3 = l3;
    let i = 0;
    while(p1 || p2) {
        const v1 = p1 ? p1.val : 0;
        const v2 = p2 ? p2.val : 0;
        const val = v1 + v2 + i;
        // 获取进位
        i = Math.floor(val / 10);
        // 取余
        p3.next = new ListNode(Math.floor(val % 10));
        
        if(p1) p1 = p1.next;
        if(p2) p2 = p2.next;
        p3 = p3.next;
    }
    
    if(i) {
        p3.next = new ListNode(i);
    }

    return l3.next;
};