代码编织梦想

一、题目

(链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

二、分析

  1. 子串是连续的,就跟子数组一样,而子序列是可以不用连续的。
  2. 用双指针算法来解决,枚举出所有可能出现的情况,再从无重复的子串中取最大值即可。max可以边枚举边更新。
  3. 如果now将一个重复的字符纳入子串,那纳入的这个字符一定是重复字符,只需要将这个重复的字符挤出子串,并在这个过程中,将挤出的字符对应的map值进行清零即可。如下图所示:

在这里插入图片描述


三、代码示例

C++版本

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int max = 0; 
        unordered_map<char, int> m;

        for(int now = 0, last = 0; now < s.size(); now++) {			// 通过now遍历所有字符,并以last来辅助截取无重复的子串,从而枚举出所有不重复的子串
            m[s[now]]++;					// now每指向一个新的字符,这个字符就算是进入了当前子串,所以要进行统计+1
            
            while(m[s[now]] > 1) {		// 去重(将重复字符挤出子串前,会一直循环,并且把循环过程中的map值清零,因为后面就是要重新计算一个子串了,跟原先子串就无关系了)
                m[s[last]]--;		// 先清除当前位置的map值
                last++;				// last再往后移动
            }

            if (max < now - last + 1) {		// 边遍历边更新max
                max = now - last + 1;
            }
        }
        return max;
    }
};

Golang版本

func lengthOfLongestSubstring(s string) int {
    last := 0
    max := 0
    m := make(map[byte]int)

    for now := 0; now < len(s); now++ {
        m[s[now]]++
        
        for m[s[now]] > 1 {
            m[s[last]] --
            last++
        }

        if max < now - last + 1 {
            max = now - last + 1
        }
    }

    return max
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/e2788666/article/details/130898581