寻找最长无重复字符子串 Longest Substring Without Repeating Characters

142 篇文章 20 订阅
45 篇文章 0 订阅

要求: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.

思路:要统计出是否有重复出现的字符,一种最快最省空间的方法就是bitmap对26个字符进行统计。

注意一点就是,在字符串匹配过程中指针回溯问题:遇到重复字符后,左指针如果只前移1步然后继续下一轮判断,这样会产生不必要的比较。比较好的一个方案是当遇到重复字符后,将左指针移到重复字符的后面。如”abcdcabc“,遇到第二'c'时发现重复时,将左指针移到第一个‘c'后的位置。然后下一轮从那开始判断。从OJ结果来看,回溯较少的方案确实节省了运行时间。

代码一:

class Solution {
public:
    unsigned int status;

    void add_to_set(char a)
    {
        int value = a - 'a';
        unsigned int t=1;
        status = status|(t<<value);
    }
    
    int exist_or_not(char a)
    {
        int value = a - 'a';
        unsigned int t=1;
        if( (status&(t<<value)) == 0) 
            return 0; //not exist
        else
            return 1; //do exist
    }

    int lengthOfLongestSubstring(string s) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int n = s.length();
		if(n==0)
			return 0;
        if(n==1)
            return 1;
        int i,j;
        int maxlen=-1;
        
		i=0;
		while(i<n)
        {
			status=0;
            j = i;
            while(j<n)
            {
                if(exist_or_not(s[j]) == 0)
                {
                    add_to_set(s[j]);
                    if(j-i+1 > maxlen)
                        maxlen = j-i+1;
                    j++;
                }
                else
                {
					while(s[i]!=s[j])
					{
						i++;
					}
					i++;
					break;
                }
            }
			if(j==n)
				break;
        }
		return maxlen;
    }

};

代码二:在代码一中,如果遇到重复字符串,会通过遍历查找前一个重复字符的位置。实际上,如果用数组int[]来存储已出现的字符的下标位置,就不用再去查找了。这样就做到真正的线性时间复杂度O(N)。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.empty())
            return 0;
        int m[256]; //m[c-'a']记录某个字符c上次出现时的位置
        memset(m, -1, sizeof(m));
        int maxlen = 1;
        int start = 0; //start记录当前非重复子串的左端位置
        for(int i=0;i<s.size();i++)
        {
            if(m[s[i]] >= start) //字符s[i]在当前已经出现过
            {
                maxlen = max(maxlen, i - start);
                start = m[s[i]] + 1; //更新当前非重复字符串
            }
            m[s[i]] = i;
        }
        maxlen = max(maxlen, (int)s.size() - start);
        return maxlen;
    }
};
PS:leetcode测试用例库发生了变化,增加了小写字母以外的字符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值