双指针

0.抽象模型

  • 初始化时准备两个指针,leftright指针,指向index=0

  • 扩大right指针,当第一次符合窗口大小时,执行逻辑

  • 在符合条件下,不断扩right,缩left,直到right达到数组或是字符串的末尾,left缩小到不符合窗口大小

这一题是leetcode的NO.3题,曾经被面到过,很经典的一道题

  • 注意:子串与子序列的区别

    • 子串:不可跳跃,如 pwwkewwke是子串

    • 子序列:可以跳跃,如pwwkewpkw是子序列

方法1:粗糙版滑动窗口

  • Set来维护重复字符与否的问题

    • 出现新的字符,很好,right指针向右扩展,并将当前字符加入Set中,更新最长无重复子串长度

    • 出现旧的字符,将左边界left指针向右收缩,移除当前的left指针指向的字符

方法2:优化版滑动窗口

  • 用一个hashmap来建立字符和其出现位置之间的映射。

  • 维护一个滑动窗口,窗口内的都是没有重复的字符,去尽可能的扩大窗口的大小,窗口不停的向右滑动。

  • (1)如果当前遍历到的字符从未出现过,那么直接扩大右边界;

  • (2)如果当前遍历到的字符出现过,则缩小窗口(左边索引向右移动),然后继续观察当前遍历到的字符;

  • (3)重复(1)(2),直到左边索引无法再移动;

  • (4)维护一个结果res,每次用出现过的窗口大小来更新结果res,最后返回res获取结果。

    • 用一个mapper记录出现过并且没有被删除的字符

    • 用一个滑动窗口记录当前index开始的最大的不重复的字符序列

    • res去记录目前位置最大的长度,每次滑动窗口更新就去决定是否需要更新res

方法3:再优化版滑动窗口

  • 常用的表如下所示:

  • 准备一个helper数组,每次记录right指针的绝对位置,

  • 更新res,更新left(拿到其最大位置)

最小覆盖子串

  • 准备两个hash arrsource target,先给t的记上,作为标准,每个字母出现的次数

  • 提供一个valid的方法,比较source target,判断source是否都包含target,包含的话true,不包含的话false

  • 然后开始构造window,最外层的条件是right<t.size(),

    • valid过不了的时候,说明window中还不含有t,记录下source,并将right++,即将window的右边界往右边推

    • valid满足条件时,说明window都能涵盖了t的字符,记录长度和res,并将source相应的字符--,将left++,缩小window的左边界

方法1

方法2

方法1:基本

方法2:多次翻转

方法1:比较字符串

方法1:翻转

方法1:暴力枚举+状态压缩

方法2:暴力枚举+挨个检查

方法1:双指针

方法2:哈希

两个hash的做法,写法很好

  • 这一题应该选择原地,没有额外空间复杂度的写法

方法1:前前双指针

  • 固定i,j指针,j指针往后滑动,如果是偶数,交换ij,并将i后滑动

方法2:前后双指针

方法1:双指针+check

  • 校验s与pattern的字符

方法1:快慢指针

[LintCode]31 · 数组划分

方法1:快速选择

Last updated