Leetcode hot 100之双指针(快慢指针、滑动窗口)

news2024/10/7 6:51:22

目录

数组

有序的平方仍有序

删除/覆盖元素

移动零:交换slow和fast

滑动窗口:最短的连续子串(r++可行解->l--最短解)

最小长度的子数组

求和:sort、l = i + 1, r = len - 1

三数之和a+b+c=target

四数之和a+b+c+d=target

颜色分类(荷兰国旗):start=0、i、end=len-1

盛水最多:start=0、end=len-1 (水=哪边,则哪边往内走)

重复数:[1, n] 

链表

相交点:长的链表先走len=long-short

倒数第n个:slow+1,fast+n

中点/回文/环:slow+1,fast+2

环入口:相遇点+1、头结点+1

归并排序

自底向上

自顶向下

双指针

数组

数组

有序的平方仍有序

删除/覆盖元素

if(nums[i] != val){
            nums[k++] = nums[i]
        }

移动零:交换slow和fast

滑动窗口

初始化left = right = 0把索引左闭右开区间[left, right)称为一个「窗口」

int left = 0, right = 0;

while (right < s.size()) {
    // 增大窗口
    window.add(s[right]);
    right++;

    while (window needs shrink) {
        // 缩小窗口
        window.remove(s[left]);
        left++;
    }
}

最小覆盖子串

function minWindow(s, t) {
    const need = new Map();
    const window = new Map();

    for (const c of t) {
        need.set(c, (need.get(c) || 0) + 1);
    }

    let left = 0;
    let right = 0;
    let valid = 0;
    let start = 0;
    let len = Infinity;

    while (right < s.length) {
        const c = s[right];
        right++;

        if (need.has(c)) {
            window.set(c, (window.get(c) || 0) + 1);

            if (window.get(c) === need.get(c)) {
                valid++;
            }
        }

        while (valid === need.size) {
            if (right - left < len) {
                start = left;
                len = right - left;
            }

            const d = s[left];
            left++;

            if (need.has(d)) {
                if (window.get(d) === need.get(d)) {
                    valid--;
                }
                window.set(d, window.get(d) - 1);
            }
        }
    }

    return len === Infinity ? "" : s.substr(start, len);
}

字符串排列/异位词

function checkInclusion(t, s) {
    const need = new Map();
    const window = new Map();

    for (const c of t) {
        need.set(c, (need.get(c) || 0) + 1);
    }

    let left = 0;
    let right = 0;
    let valid = 0;
    
    while (right < s.length) {
        const c = s[right];
        right++;

        if (need.has(c)) {
            window.set(c, (window.get(c) || 0) + 1);
            
            if (window.get(c) === need.get(c)) {
                valid++;
            }
        }
//与最小覆盖串的区别
        while (right - left >= t.length) {
            if (valid === need.size) {
                return true;
            }
//与最小覆盖串的区别            
            const d = s[left];
            left++;

            if (need.has(d)) {
                if (window.get(d) === need.get(d)) {
                    valid--;
                }
                window.set(d, window.get(d) - 1);
            }
        }
    }
    
    return false;
}

最长无重复子串

function lengthOfLongestSubstring(s) {
    const window = new Map();

    let left = 0;
    let right = 0;
    let res = 0; // 记录结果

    while (right < s.length) {
        const c = s[right];
        right++;
        
        // 进行窗口内数据的一系列更新
        window.set(c, (window.get(c) || 0) + 1);
        
        // 判断左侧窗口是否要收缩
        while (window.get(c) > 1) {
            const d = s[left];
            left++;
            
            // 进行窗口内数据的一系列更新
            window.set(d, window.get(d) - 1);
        }
        
        // 在这里更新答案
        res = Math.max(res, right - left);
    }

    return res;
}

最小长度的子数组

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s长度最小连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

类似于前缀和:区间求和

let ans = Infinity
    
    while(end < len){
        sum += nums[end];
        while (sum >= target) {
            ans = Math.min(ans, end - start + 1);
            sum -= nums[start];
            start++;
        }
        end++;
    }

求和:sort、l = i + 1, r = len - 1

三数之和a+b+c=target

arr.sort()

 let l = i + 1, r = len - 1, iNum = nums[i]
        // 数组排过序,如果第一个数大于0直接返回res
        if (iNum > 0) return res
        // 去重
        if (iNum == nums[i - 1]) continue
        while(l < r) {
            if (threeSum < 0) l++ 
            else if (threeSum > 0) r--
            else {
                res.push([iNum, lNum, rNum])
                // 去重
                while(l < r && nums[l] == nums[l + 1]){
                    l++
                }
                while(l < r && nums[r] == nums[r - 1]) {
                    r--
                }
          
                l++
                r--
            } 
         }

四数之和a+b+c+d=target

    for(let i = 0; i < len - 3; i++) {
        // 去重i
        if(i > 0 && nums[i] === nums[i - 1]) continue;

颜色分类(荷兰国旗):start=0、i、end=len-1

盛水最多:start=0、end=len-1 (水=哪边,则哪边往内走)

重复数:[1, n] 

T(n):O(n)。「Floyd 判圈算法」时间复杂度为线性的时间复杂度。

S(n):O(1)。只需要常数空间存放若干变量。

对 nums数组建图,每个位置 i连一条 i→nums[i] 的边。由于存在的重复的数字 target,因此 targe这个位置一定有起码两条指向它的边,因此整张图一定存在环,且我们要找到的 target就是这个环的入口

var findDuplicate = function(nums) {
    let slow = 0, fast = 0;
    do {
        slow = nums[slow];
        fast = nums[nums[fast]];
    } while (slow != fast);
    slow = 0;
    while (slow != fast) {
        slow = nums[slow];
        fast = nums[fast];
    }
    return slow;
};

链表

相交点:长的链表先走len=long-short

倒数第n个:slow+1,fast+n

中点/回文/环:slow+1,fast+2

环入口:相遇点+1、头结点+1

相遇时: slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A

(x + y) * 2 = x + y + n (y + z)

x = (n - 1) (y + z) + z

虽然实际中的n>1,当 n为1的时候,公式就化解为 x = z

从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点

归并排序

自底向上

 T(n):O(nlogn)

S(n):O(1)

空间复杂度不是累计的,而是计算使用空间的峰值,

C/C++ 没有回收资源(new完后需要delete,不然内存泄漏照样是O(logn)),

但是像 java ,js这类语言会自动回收资源的

每次将链表拆分成若干个长度为 subLength 的子链表(最后一个子链表的长度可以小于 subLength)

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val? 0 : val)
 *     this.next = (next? null : next)
 * }
 */
const merge = (head1, head2) => {
    let temp =  new ListNode(0), temp1 = head1, temp2 = head2;
    while (temp1&& temp2) {
        if (temp1.val <= temp2.val) {
            temp.next = temp1;
            temp1 = temp1.next;
        } else {
            temp.next = temp2;
            temp2 = temp2.next;
        }
        temp = temp.next;
    }
    if (temp1 !== null) {
        temp.next = temp1;
    } else if (temp2 !== null) {
        temp.next = temp2;
    }
    return dummyHead.next;
}

var sortList = function(head) {
    if (head === null) {
        return head;
    }
    //获取长度
    let length = 0;
    let node = head;
    while (node !== null) {
        length++;
        node = node.next;
    }

    const dummyHead = new ListNode(0, head);

    for (let subLength = 1; subLength < length; subLength <<= 1) {
        let prev = dummyHead, curr = dummyHead.next;

        while (curr !== null) {
            let head1 = curr;
            for (let i = 1; i < subLength && curr.next; i++) {
                curr = curr.next;
            }

            let head2 = curr.next;
            curr.next = null;
            curr = head2;
            for (let i = 1; i < subLength && curr&& curr.next; i++) 
                curr = curr.next;
            }

            let next = null;
            if (curr) {
                next = curr.next;
                curr.next = null;
            }
            const merged = merge(head1, head2);
           //通过 prev 指针将已排序的子链表连接到一起
            prev.next = merged;

            while (prev.next) {
                prev = prev.next;
            }
           //用 curr 指针继续遍历未排序的部分
            curr = next;
        }
    }
    return dummyHead.next;
};

自顶向下

操作

内部排序

思想

稳定

平均

S(n)

T(n)

平均

最坏

最好

2-路归并

分治;分组排序,两两合并 相邻 有序序列

n

nlog2n

nlog2n逆序

nlog2n顺序

双指针
const merge = (head1, head2) => {
    const dummyHead = new ListNode(0);
    let temp = dummyHead, temp1 = head1, temp2 = head2;
    while (temp1 !== null && temp2 !== null) {
        if (temp1.val <= temp2.val) {
            temp.next = temp1;
            temp1 = temp1.next;
        } else {
            temp.next = temp2;
            temp2 = temp2.next;
        }
        temp = temp.next;
    }
    if (temp1 !== null) {
        temp.next = temp1;
    } else if (temp2 !== null) {
        temp.next = temp2;
    }
    return dummyHead.next;
}

const toSortList = (head, tail) => {
    if (head === null) {
        return head;
    }
    if (head.next === tail) {
        head.next = null;
        return head;
    }
    let slow = head, fast = head;
    while (fast !== tail) {
        slow = slow.next;
        fast = fast.next;
        if (fast !== tail) {
            fast = fast.next;
        }
    }
    const mid = slow;
    return merge(toSortList(head, mid), toSortList(mid, tail));
}

var sortList = function(head) {
    return toSortList(head, null);
};
数组
  • key:
  1. left=arr.slice(0,mid)
  2. mergeLeft=mergeSort(left)
  3. res.push(leftArr.shift())
  4. res=res.concat(leftArr)
 function   mergesort(arr){
            if(arr.length<2)return  arr
            let  len=arr.length
            let  mid=parseInt(len/2)
            let l1=arr.slice(0,mid)
            let  r1=arr.slice(mid,len)
            let  mergeleft=mergesort(l1)
            let mergeright=mergesort(r1)

            return merge(mergeleft,mergeright)

            function merge(left,right){
                let res=[]
                while(left.length&&right.length){
                    if(left[0]<=right[0]){
                        res.push(left.shift())
                    }else{
                        res.push((right.shift()))
                    }
                }
                if(left.length){
                    res=res.concat(left)
                }
                if(right.length){
                    res=res.concat(right)
                }
                return  res
            }
         
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1066031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

table表格初始化根据字段数字排序,table表格进入后返回上一级设置,第一级隐藏

根据字段数字排序 // 初始化表格数据 const getTableData async () > {try {loading.value trueconst res await getFileList() //排序const sortedData computed(() > {return res.slice().sort((a: any, b: any) > a.documentType - b.documentType);});tableD…

【Spring Boot | 第一篇】Spring Boot 原理

前言&#xff1a; 当今互联网时代&#xff0c;随着软件开发的快速发展&#xff0c;开发者们迫切需要一个简单、高效、可扩展的框架来提升开发效率和质量。Spring Boot作为一款备受欢迎的Java框架&#xff0c;应运而生。 Spring Boot以其优雅的设计和丰富的功能&#xff0c;成…

2023年中国铁路行车监测系统竞争格局、市场规模及行业发展趋势分析[图]

铁路行车监测系统是对铁路列车及车载设备运行状态全面监测的车载行车安全系统&#xff0c;是智能化、自动化等技术在铁路行业的具体应用。行车监测系统主要包括机车车载安全防护系统&#xff08;简称6A系统&#xff09;、机车远程监测与诊断系统&#xff08;简称CMD系统&#x…

编译工具链 之二 详解 ELF 格式及标准、UNIX 发展、ABI

在计算机及嵌入式系统中&#xff0c;二进制文件也有一定的标准格式&#xff0c;通常会包含在各平台的应用程序二进制接口 &#xff08;Application Binary Interface&#xff0c;ABI&#xff09;规范中。它是编译工具链必须要遵守的规范&#xff08;编译工具链产生符合 ABI 的二…

【数字图像处理第四版课后习题答案】第2章 数字图像基础(含英文原版)

2.1暂无 2.2 翻译答案 如图 P2.3 所示&#xff0c;视网膜图像中与点相对应的直径 x 是由类似的三角形得到的。即 得出 x 0.085d。根据第 2.1 节中的讨论&#xff0c;并结合一些自由解释&#xff0c;我们可以将眼窝视为一个方形传感器阵列&#xff0c;拥有大约 337,000 个元素…

6-3 递增的整数序列链表的插入 分数 5

List Insert(List L, ElementType X) {//创建结点List node (List)malloc(sizeof(List));node->Data X;node->Next NULL;List head L->Next; //定位real头指针//空链表 直接插入if (head NULL) {L->Next node;node->Next head;return L;}//插入数据比第…

一文全面解读CKA认证的含金量、详细介绍!

K8s是目前最流行的开源容器编排引擎&#xff0c;在全球都得到了广泛应用&#xff0c;BAT、京东、360、华为、网易、IBM、知乎等国内外诸多知名公司都在基于K8s构建企业容器云平台&#xff0c;支撑公司业务&#xff0c;越来越多的企业也都在向K8s迁移。相信在不远的将来&#xf…

winform中DevExpress控件一些属性

1.DevExpress控件bar去掉前面四点和后面的倒三角。 如图。设置bar属性optionsBar→allowQuickCustomizationFALSE

Leetcode hot 100之前缀和、差分数组、位运算

目录 差分数组-区间增减 和为K的子数组&#xff1a;前缀和 哈希表优化 除自身以外数组的乘积&#xff1a;前后缀区间 差分数组-区间增减 想对区间 nums[i..j] 的元素全部加 3&#xff0c;那么只需要让 diff[i] 3&#xff0c;然后再让 diff[j1] - 3 和为K的子数组&#x…

广州华锐互动:VR动物解剖实验室带来哪些便利?

随着科技的不断发展&#xff0c;我们的教育方式也在逐步变化和进步。其中&#xff0c;虚拟现实(VR)技术的应用为我们提供了一种全新的学习方式。尤其是在动物解剖实验中&#xff0c;VR技术不仅能够增强学习的趣味性&#xff0c;还能够提高学习效率和准确性。 由广州华锐互动开发…

Web_python_template_injection SSTI printer方法

这题挺简单的 就是记录一下不同方法的rce python_template_injection ssti了 {{.__class__.__mro__[2].__subclasses__()}} 然后用脚本跑可以知道是 71 {{.__class__.__mro__[2].__subclasses__()[71]}} 然后直接 init {{.__class__.__mro__[2].__subclasses__()[71].__i…

实战纪实 | 某米企业src未授权访问

公众号&#xff1a;掌控安全EDU 分享更多技术文章&#xff0c;欢迎关注一起探讨学习 某米企业src漏洞挖掘 这一挖就挖到了一个未授权操作漏洞&#xff0c;写个文章记录下~~ 通过信息收集&#xff0c;发现这么一个资产。 访问 http://xxx.com 如下图所示 1.点击头像-点击授权登…

【SQL Server】表死锁/解锁和sql语句分析

文章目录 表死锁查询锁的进程解锁 sql语句分析来源 表死锁 查询锁的进程 1 首先创建一个测试用的表&#xff1a; CREATE TABLE Test ( TID INT IDENTITY(1,1) ) 2 执行下面的SQL语句将此表锁住&#xff1a; SELECT * FROM Test WITH (TABLOCKX) 3 通过下面的语句可以查看…

【CMU15-445 Part-17】Two-Phase Locking

Part17-Two-Phase Locking Lock Types S-LOCK 共享锁 for reads X-LOCK 排他锁 for writes 上述T1最后R(A) 会导致不可重复读 2PL 允许数据库系统始终以保证Conflict Serializable schedule情况下分发lock Phase #1 Growing 每个txn请求locks 从lock managerlock manager…

万界星空科技云MES系统生产全流程追溯功能介绍

制造业工厂产品质量贯穿于产品的整个生命周期&#xff0c;也是企业参与市场竞争求生存求发展的基础&#xff0c;而制造过程中出现的产品质量问题则是产品最终质量的基石。 随着全球市场竞争的进一步加剧和制造业信息化进程的加快&#xff0c;企业对产品制造过程的质量信息管理…

1876. 长度为三且各字符不同的子字符串

1876. 长度为三且各字符不同的子字符串 C代码&#xff1a;滑动窗口 // 存在三种字符&#xff0c;且不重复、子串数量 int countGoodSubstrings(char * s){int k 3;int hash[26] {0};int len 0;int l 0;int ans 0;for (int i 0; i < strlen(s); i) {hash[s[i] - a];if…

c#设计模式-行为型模式 之 策略模式

&#x1f680;简介 &#x1f424;作为一个开发人员&#xff0c;开发需要选择一款开发工具&#xff0c;如在编写C#时&#xff0c;我们可以选择VisualStudio进行开发&#xff0c;也可以使用Rider 进行开发。 &#x1f433;该模式定义了一系列算法&#xff0c;并将每个算法封装起来…

最新天津python培训机构 Python培训的重要性

Python编程语言近年来备受瞩目&#xff0c;其简洁、易学、多用途的特点受到了众多程序员的喜爱。随着Python的普及程度不断提高&#xff0c;越来越多的人开始关注和学习Python。 Python培训的重要性 Python作为一门编程语言&#xff0c;具有广泛的应用领域&#xff0c;如数据…

linux5.10的一个警告Kernel image misaligned at boot, please fix your bootloader!

平台&#xff1a;rk3399linux5.10 问题&#xff1a;发现启动时有一个内核警告信息 Kernel image misaligned at boot, please fix your bootloader! 后面的数字是我打印的地址信息。 不知道这个内核搞一个这样的警告是什么原因&#xff0c;我就没有继续深挖啦。 一、通过搜…