无重复字符的最长子串(leetcode-3)

题目

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是子串的长度,"pwke" 是一个子序列,不是子串。

思路

双指针法。看到这种“连续”、“最大”、“最长”的就应该想到双指针。双指针是专门用来解决最长的序列的一系列问题的。

双指针其实也是一种贪心。主要思想是:用一个指针(左指针)指向最左边,另一个指针(右指针)从第一个元素开始遍历。两个指针夹起来的部分就是一个子串。只要这个子串没有相同字符,那么右指针就一直右移。直到,右指针的字符重复了,那么左指针右移。这就相当于,将左边的长度缩短。然后重复上述操作。

这种贪心是对的,因为如果最短的子串都不满足要求,那么更大的子串一定不满足(仔细想想应该能想出来)。

代码

# include <iostream>
# include <string>
# include <algorithm>
# include <unordered_set>
using namespace std;

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int lp = 0, rp = 0;
        int ans = 0;
        unordered_set <char> unique_set;
        // 左指针指向
        while (lp < s.size())
        {
            // 右边能走就一直走
            while (unique_set.find(s[rp]) == unique_set.end() && rp < s.size()) 
                unique_set.insert(s[rp++]);

            // 不能就删除左边一个
            ans = max(ans, (int)unique_set.size());
            unique_set.erase(s[lp++]);
        }
        return ans;
    }
};

int main() {
    Solution a = Solution();
    printf("%d\n", a.lengthOfLongestSubstring("abcabcbc"));
    printf("%d\n", a.lengthOfLongestSubstring("bbbbbb"));
    printf("%d\n", a.lengthOfLongestSubstring("pwwkew"));
}


posted @ 2020-11-01 10:32  Destiny233  阅读(58)  评论(0)    收藏  举报