Longest Substring Without Repeating Characters

寻找最长无重复字符子串
本文介绍了一种算法用于查找给定字符串中最长的不包含重复字符的子串,并详细解释了其工作原理和优化过程。通过使用哈希表记录字符索引,算法能够高效地解决此问题。

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

For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. 

For "bbbbb" the longest substring is "b",with the length of 1.

 

思路:要找最长的不包含重复字符的子串。设置两个指针left和right,分别指向当前不包含重复字符的子串的首尾,依次扫描原字符串的每个字符,right一直向前走,当碰到重复字符时,就需要改变left的指向,即该重复字符上次出现位置的下一个位置。


如何判断找到重复字符呢?很容易想到要用hash表,所以,一开始想到的算法如下:

void resethash(char *left, char *right, int *hash, char *src)
{
    int i;
    for(i = 0; i < 128; i++)
    {
        hash[i] = -1;
    }
    while(left < right)
    {
        hash[*left] = left - src;
        left++;
    }
}

int lengthOfLongestSubstring(char* s) 
{
    int hash[128] = {};
    char *left, *right;
    int i, j;
    int res = 0;

    for(i = 0; i < 128; i++)
    {
        hash[i] = -1;
    }
    for(left = right = s, i = 0; s[i] != '\0'; i++, right++)
    {
        if(hash[*right] != -1)
        {
            if(res < right - left)
            {
                res = right - left;
            }
            
            j = hash[*right];
            left = s + j + 1;
            resethash(left, right, hash, s);
        }
        hash[*right] = i;
    }
    if(res < right - left)
    {
        res = right - left;
    }
    return res;
}

  该算法在leetcode上的测试时间为36 ms。在hash表中记录每个字符的索引,当碰到重复字符时,重置该hash表,也就是该hash表只记录不包含重复字符子串的索引。这是可以优化的地方。


举个例子:str=”abcdefgda”,当扫描到第二个’d’时,查看当前hash表发现有重复字符,因此需要把left指向’e’,right继续向后走扫描到’a’。因为’a’在之前也出现过,但是此时left已经指向了’e’,所以需要把left之前的字符都从hash表中抹去,表明当前得到的子串已不再包含’a’了,从而在第二次遇见’a’时就可以接纳它。


因为hash表记录了每个字符的索引,所以完全可以利用left指针,而无需重置hash表。查询hash表,如果得到当前字符的索引在left之前,就表明当前的非重复子串可以接纳该字符。新算法的运行时间为8ms,算法如下:

int lengthOfLongestSubstring(char* s) 
{
    int hash[128] = {};
    char *left, *right;
    int i, j;
    int res = 0;

    for(i = 0; i < 128; i++)
    {
        hash[i] = -1;
    }
    for(left = right = s, i = 0; s[i] != '\0'; i++, right++)
    {
        if(hash[*right] >= left-s)
        {
            left = hash[*right] + 1 + s;
        }
        if(res < right - left + 1)
        {
            res = right - left + 1;
        }
        hash[*right] = i;
    }
    return res;
}

  

 

转载于:https://www.cnblogs.com/gqtcgq/p/7247156.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值