LeetCode 3. Longest Substring Without Repeating Characters

3. Longest Substring Without Repeating Characters

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

Examples:

Given “abcabcbb”, the answer is “abc”, which the length is 3.

Given “bbbbb”, the answer is “b”, with the length of 1.

Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

题目描述:
给出一个字符串s,找出字符串里面最长的不包括相同字符的子字符串。

解题思路:
要解决这道题可以从左到右遍历字符串,从第一个字符开始,直到找到第一个出现重复的字符,这个区间内的子字符串就是一个不包含重复字符的字符串。然后从第一次出现这个重复字符的下一个位置开始往后找,知道找到一个重复的字符或到了字符串的结尾。通过这种方法,我们可以找到其中所有的不包含重复字符的子字符串,因为题目只要求返回最长的子字符串的长度,所以这里我也只保留了最长的长度。
我觉得其中比较关键的问题是要知道哪个字符是出现过的?在哪里出现了?为了解决这两个问题,我通过一个数组来保存每种字符的最近出现的位置,至于这里的字符数,也就是这个数组的长度,我尝试了128和256,都是可以的。在这个数组中,用字符的ascii码作为下标,对应的值就是这个字符最近出现的位置,例如’a’的ascii码为97,假设这个数组的第97个元素值为2,那么’a’第一次出现在字符串的第2个位置。这个数组的元素会被初始化为-1,在后面的遍历过程中这些值会被更新。
另外我还用了一个startIndex变量来记录当前搜索的子字符串的开始位置。结合这个startIndex和上述的记录字符最近出现位置的数组,就可以判断这个字符是在当前子字符串中出现过

  • 当某个字符的最近出现位置比startIndex小,那么表示这个字符在当前子字符串中是没有出现过的。
  • 当某个字符的最近出现位置比startIndex大或者与startIndex相等,那么证明这个字符在startIndex和当前位置之间已经出现了一次,说明当前位置的字符是重复的。此时需要把startIndex移动到上一次出现这个重复字符的下一个位置。

以题目给出的”pwwkew”为例,一个完整的过程如下图:
这里写图片描述
可以看到第(4)步,当遍历到第二个’W’的时候,因为此时的’W’上一个出现位置是1,比startIndex(此时值为0)要大,所以更新startIndex为上一次出现’W’的下一个位置,也就是更新startIndex为2,同时更新’W’的上一次出现位置为2,继续后续的遍历。

代码:

#include <iostream>
#include <string>

using namespace std;

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int charCount = 256;
        int startIndex = 0;
        int max = 0;
        int* charToLastPos = new int[charCount];
        for (int i = 0; i < charCount; i++) charToLastPos[i] = -1;
        for (int index = 0; index < s.size(); index++) {
            if (charToLastPos[s[index]] < startIndex) { 
                charToLastPos[s[index]] = index;
            }
            else {
                max = max < index - startIndex ? index - startIndex : max;
                startIndex = charToLastPos[s[index]] + 1;
                charToLastPos[s[index]] = index;
            }
            if (index == s.size() - 1 && max < s.size() - startIndex) {
                return s.size() - startIndex;
            }
        }
        return max;
    }
};

int main(int argc, char** argv) {
    Solution sln;
    cout << sln.lengthOfLongestSubstring("pwwkew") << endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值