字符串高频算法:无重复字符的最长子串

题目

3. 无重复字符的最长子串 - 力扣(LeetCode)

解题思路

思路

方法: 滑动窗口

[!简单思路]
[^1]以示例一中的字符串 abcabcbb 为例,找出==从每一个字符开始的,不包含重复字符的最长子串==,其中最长的那个字符串即为答案。

对于示例一中的字符串,我们列举出这些结果,其中括号中表示选中的字符以及最长的字符串:

以 (a)bcabcbb 开始的最长字符串为 (abc)abcbb;
以 a(b)cabcbb 开始的最长字符串为 a(bca)bcbb;

[!为什么可以使用滑动窗口]
依次递增地枚举子串的起始位置,那么子串的结束位置也是递增的!这里的原因在于,假设我们选择字符串中的第 k 个字符作为起始位置,并且得到了不包含重复字符的最长子串的结束位置为 r
k​。那么当我们选择第 k+1 个字符作为起始位置时,首先从 k+1 到 r
k的字符显然是不重复的,并且由于少了原本的第 k 个字符,我们可以尝试继续增大 r
k,直到右侧出现了重复字符为止。
这样一来,我们就可以使用「滑动窗口」来解决这个问题了:

具体实现

分析Set方法在最长无重复子串问题中的应用

在本题中,使用了哈希集合的

  1. has(value)
- 用于检查集合中是否存在某个字符。在代码中,`occ.has(s.charAt(rk + 1))`用于判断当前字符是否已经存在于集合中。
  1. add(value)

    • 用于将一个字符添加到集合中。在代码中,occ.add(s.charAt(rk + 1))用于将新遇到的字符添加到集合中。
  2. delete(value)

    • 用于从集合中删除某个字符。在代码中,occ.delete(s.charAt(i - 1))用于在窗口左指针向右移动时,删除窗口左边界的字符。
  • 滑动窗口法

    • 使用双指针(irk)来维护一个滑动窗口,确保窗口内的字符都是不重复的。

    • i 表示窗口的左边界,rk 表示窗口的右边界。

  • Set的使用

    • occ 是一个Set,用于存储当前窗口中的字符。

    • 在外层循环中,每次左指针i移动时,会删除前一个左边界字符。

    • 内层循环中,右指针rk不断向右移动,直到遇到重复字符为止。

AC代码

var lengthOfLongestSubstring = function(s) {

    const occ = new Set(); // 创建哈希集合, 用户判断字符串是否重复

    const n = s.length; // 记录下s字符串的长度

    // 初始化右指针为 rk = -1, 表示右指针初始状态在字符串左边缘的左侧, 这样比较合理

    let rk = -1, ans = 0; // ans用来记录最终最大字符串的长度

    for(let i = 0; i < s.length; i++) {

        // 左指针向右移动一格, 移除一个字符

        if(i != 0) {

            occ.delete(s.charAt(i - 1));

        }

        // 右指针不越界并且右指针不是重复字符时

        while (rk + 1 < n && !occ.has(s.charAt(rk + 1))) {

            occ.add(s.charAt(rk + 1));

            ++rk;

        }

        ans = Math.max(ans, rk - i + 1)

    }

    return ans;

}
  • rk - i + 1

    • 当前窗口的长度是右指针 rk 减去左指针 i 加 1。这是因为索引是从 0 开始的,比如从索引 irk 的字符总共有 rk - i + 1 个。
  • Math.max(ans, rk - i + 1)

    • ans 保存的是当前找到的最长无重复子串的长度。

    • Math.max 会比较 ans 和当前窗口的长度,取较大的值作为新的 ans,确保 ans 始终记录最长的窗口长度。

判断重复字符

使用哪种数据结构来判断 是否有重复的字符?
——JavaScript 中的 Set
在 JavaScript 中,要判断字符串中是否包含重复字符,可以使用 Set 数据结构。Set 是一种特殊的数据结构,它存入的值都是唯一的,不会有重复。

[!Set 判断字符串中是否有重复字符的步骤]

步骤:

1 将字符串转为字符数组
(将字符串拆分为单个字符组成的数组,以便逐个检查字符)
2 使用 Set 存储字符:
将字符数组中的每个字符存入 Set 中
3 比较 Set 的大小和原字符串的长度
如果 Set 的大小和原字符串的长度不同,说明存在重复字符,因为 Set 会自动去重.

你可能感兴趣的:(算法)