闯关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 * 10^4^
  • 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

相关推荐
Lenyiin2 分钟前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码9 分钟前
Cmd命令大全(万字详细版)
python·算法·小程序
scan72424 分钟前
LILAC采样算法
人工智能·算法·机器学习
菌菌的快乐生活44 分钟前
理解支持向量机
算法·机器学习·支持向量机
大山同学1 小时前
第三章线性判别函数(二)
线性代数·算法·机器学习
axxy20001 小时前
leetcode之hot100---240搜索二维矩阵II(C++)
数据结构·算法
黑客Ash1 小时前
安全算法基础(一)
算法·安全
AI莫大猫2 小时前
(6)YOLOv4算法基本原理以及和YOLOv3 的差异
算法·yolo
taoyong0012 小时前
代码随想录算法训练营第十一天-239.滑动窗口最大值
c++·算法
Uu_05kkq2 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法