[力扣C语言实现]3.无重复字符的最长子串

3.无重复字符的最长子串

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

示例 1:

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

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

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

输入: s = “”
输出: 0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

int lengthOfLongestSubstring(char * s){
    
    
    int hashmap[128] = {
    
    0};
    int left = 0;
    int right = 1;
    int maxlen = 0;

    if (strlen(s) <= 1)
    {
    
    
        return strlen(s);
    }

    hashmap[s[left]] = 1;

    while (s[right] != '\0')
    {
    
    
        if (hashmap[s[right]] > 0)
        {
    
    
            if (maxlen < right - left)//出现了重复字母,先计算本次的滑动窗口大小,若其大于之前的最大滑动窗口大小,则更新窗口值
            {
    
    
                maxlen = right - left;
                printf("maxlen: %d\n",maxlen);
            }

            if (left < hashmap[s[right]])//左窗口的滑动要保证其是向右滑,而不是向左滑
            {
    
    
                left = hashmap[s[right]];//left是从0开始的,而hashmap从1开始,所以这里left=hashmap[s[right]]的意思是left滑动到出现的重复字符处,比如abca,未滑动前left=0,而当hashmap[s[3]]时发现a之前有了,那么left就要滑动到第一个a的前面,所以left = hashmap['a'].
            }
        }

        hashmap[s[right]] = right+1;
        right++;
    }

    if (maxlen < strlen(s) - left)
    {
    
    
        maxlen = strlen(s) - left;
    }

    return maxlen;
}

滑动窗口讲解:

我们使用滑动窗口来记录当下最长不重复的子串,首先窗口大小为0,左指针left作为左窗口,指向第一个元素,并使用hashmap记录每一个字符的位置,但是由于我们的hashmap初始化全为0,所以我们记录元素的坐标,如果从0开始的话就会有歧义,分不清是hashmap的原始值还是第一个元素的下标,所以对于hashmap,我们使用1来表示元素的起始位置。

右指针right代表右窗口,指向第二个元素。此时,我们从第二个元素开始判断,若该元素之前没有在滑动窗口中出现过: hashmap[right] ==0,那么我们就将它加入滑动窗口:hashmap[right] = right+1;right++;

当遍历到某个字符,该字符已经在滑动窗口中出现过了,比如hashmap[‘a’] > 0,那么我们就要移动滑动窗口的左指针,滑动的目的是为了去重,那么就要滑动到已经出现了的’a’的后一个位置,即 left = hashmap[right];,

详细代码实现如下:

if (hashmap[s[right]] > 0)
{
    
    
    if (maxlen < right - left)//出现了重复字母,先计算本次的滑动窗口大小,若其大于之前的最大滑动窗口大小,则更新窗口值
    {
    
    
        maxlen = right - left;
        printf("maxlen: %d\n",maxlen);
    }

    if (left < hashmap[s[right]])//左窗口的滑动要保证其是向右滑,而不是向左滑
    {
    
    
        left = hashmap[s[right]];//left是从0开始的,而hashmap从1开始,所以这里left=hashmap[s[right]]的意思是left滑动到出现的重复字符处,比如abca,未滑动前left=0,而当hashmap[s[3]]时发现a之前有了,那么left就要滑动到第一个a的前面,所以left = hashmap['a'].
    }
}

首先,hashmap[s[right]] > 0表示字母s[right]已经出现过一次了,那么我们已经到了“不重复”----->“重复”的临界点,所以我们此时要计算这个当前的最大的不重复的最长子串的长度,以便判断是否需要更新我们的不重复子串的最大长度值maxlen。

其次,滑动,为什么要加一个“ if (left < hashmap[s[right]])”的判断呢?因为滑动只能在当前窗口的基础上向右滑动,如果又滑动到当前滑动窗口左边界的左边的空间,那么就不对了。

猜你喜欢

转载自blog.csdn.net/dengwodaer/article/details/115017873