闯关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

相关推荐
kaikaile19954 小时前
MATLAB计算卫星星下点轨迹
开发语言·算法·matlab
_OP_CHEN4 小时前
【算法基础篇】(三十一)动态规划之基础背包问题:从 01背包到完全背包,带你吃透背包问题的核心逻辑
算法·蓝桥杯·动态规划·背包问题·01背包·完全背包·acm/icpc
长安er4 小时前
LeetCode876/141/142/143 快慢指针应用:链表中间 / 环形 / 重排问题
数据结构·算法·leetcode·链表·双指针·环形链表
Aaron15884 小时前
电子战侦察干扰技术在反无人机领域的技术浅析
算法·fpga开发·硬件架构·硬件工程·无人机·基带工程
zhglhy5 小时前
Jaccard相似度算法原理及Java实现
java·开发语言·算法
仰泳的熊猫5 小时前
1140 Look-and-say Sequence
数据结构·c++·算法·pat考试
handuoduo12345 小时前
SITAN中avp必要性分析
人工智能·算法·机器学习
zl_vslam5 小时前
SLAM中的非线性优-3D图优化之相对位姿Between Factor右扰动(八)
人工智能·算法·计算机视觉·3d
EXtreme355 小时前
栈与队列的“跨界”对话:如何用双队列完美模拟栈的LIFO特性?
c语言·数据结构·leetcode·双队列模拟栈·算法思维
电饭叔5 小时前
如何代码化,两点之间的距离
笔记·python·算法