闯关leetcode——3.Longest Substring Without Repeating Characters

大纲

题目

地址

https://leetcode.com/problems/longest-substring-without-repeating-characters/description/

内容

Given a string s, find the length of the longest substring without repeating characters.

Example 1:

Input: s = "abcabcbb"

Output: 3

Explanation: The answer is "abc", with the length of 3.

Example 2:

Input: s = "bbbbb"

Output: 1

Explanation: The answer is "b", with the length of 1.

Example 3:

Input: s = "pwwkew"

Output: 3

Explanation: The answer is "wke", with the length of 3.

Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.

Constraints:

  • 0 <= s.length <= 5 * 104
  • s consists of English letters, digits, symbols and spaces.

解题

这题是要在一个只包含English letters, digits, symbols and spaces 的字符串中找打最长 的不重复 子串。

一种比较容易想到的思路是:遇到重复的字符,则从上次这个字符出现的位置的后个位置开始尝试比较。比如abcdef是当前最长不重复子串。如果后面出现的字符是b,则从下标为1的b的后一位(c)开始组成新的测试子串,即cdefb。当新的测试子串的长度大于当前最长的子串,则更新该最大长度值。

为了判断后续出现的字符是否已经存在于当前最长子串中,则可以考虑使用map<char,int>的结构来存储最长子串及其坐标信息。但是这个题目存在只包含English letters, digits, symbols and spaces 的条件,这意味着每个字符都是ASCII码中的字符------它只有128个------且是连续的数字(见https://baike.baidu.com/item/ASCII/309296)。我们可以充分利用这个条件,使用一个更加紧凑高效的结构来存储这个关系。

cpp 复制代码
        array<int, 128> charIndex;
        charIndex.fill(-1);

然后我们遍历整个字符串,将这样的关系存储起来。

cpp 复制代码
for (int i = 0; i < s.size(); i++) {
......
	charIndex[int(s[i])] = i;
......
}

这儿有一个问题:在寻找过程中,如果最长子串发生了变化,则被剔除出的字符串是否应该从charIndex中剔除?比如上例abcdef是最长子串时,charIndex包含这些字符以及它们的位置。如果在f后面新出现的字符是b,则要开始新探索的子串是cdefb,这个时候字符a是否需要从charIndex中剔除?因为它可能会影响到后续再次出现a时的判断。实际我们通过新探索的子串开头第一个字符位置来判断新的重复是否需要处理。在这个例子中,第一个a(绿色)位于新子串cdefb起始位置(箭头处)的左侧,即使它存在charIndex中,也不会影响后续的探索,即我们可将新的探索子串定义为cdefba。假设下一个出现的是字符d,由于上一次出现的d位于子串起始位置(箭头处)的右侧,所以需要重新探索新的子串

经过分析,我们知道子串起始位置也是需要记录,以用于辅助判断是否要使用新子串。

由于该题只是要输出最长子串长度,并不要求输出最长子串的内容,所以我们并不用记录子串的具体顺序,只要比较并保留最长的一条串的长度即可。

最长串的比较maxLen = max(maxLen, i - start)可以优化到串的起始位置发生变化的时候进行。这样可以将对比的次数降到最低。

cpp 复制代码
#include <string>
#include <array>
using namespace std;

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        array<int, 128> charIndex;
        charIndex.fill(-1);
        int start = 0;
        int maxLen = 0;
        for (int i = 0; i < s.size(); i++) {
            if (charIndex[int(s[i])] >= start) {
                maxLen = max(maxLen, i - start);
                start = charIndex[int(s[i])] + 1;
            }
            charIndex[int(s[i])] = i;
        }

        if (s.size() - start > maxLen) {
            maxLen = s.size() - start;
        }
        
        return maxLen;
    }
};

上述代码的一个边界问题是:最长子串的尾部正好是原始串的尾部。这样我们必须在遍历结束后,考虑这种情况下最长子串的可能性。

代码地址

https://github.com/f304646673/leetcode/tree/main/3-Longest-Substring-Without-Repeating-Characters

相关推荐
朝朝辞暮i5 小时前
C++ 第 21 课:struct —— 把一组相关数据打包在一起
开发语言·c++·算法
青梅橘子皮5 小时前
Blue---二分算法(二分查找与二分答案)
算法
长河5 小时前
Java的GC(垃圾回收)中,标记无用对象的核心方法是可达性分析算法
java·jvm·算法
月光船幽幽5 小时前
加性偏移外推提升参数识别可靠性
python·算法
Ivanqhz6 小时前
层归一化、残差、前馈网络与激活函数简述
服务器·数据库·人工智能·深度学习·算法
不会就选b7 小时前
算法日常・每日刷题--<动态规划>3
数据结构·算法
-dzk-8 小时前
【堆】LC 347.前 K 个高频元素
算法·堆
H.莓飛8 小时前
【数据结构】栈_OJ题
linux·数据结构·算法·centos
Zootopia6268 小时前
多架 eVTOL集群排班调度方案思考
人工智能·算法·数学建模·matlab·动态规划·无人机·evtol
和裕8 小时前
年度框架直供 vs 零散按需采购:定制纸箱采购成本、交付与服务核心区别全对比
大数据·运维·网络·人工智能·算法