[LeetCode]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.

寻找没有重复字符的最长子串的长度,解法是这样的:

首先考虑这样的字串,如"dabcabc",开始很顺利地从字符串的头往后扫描,当前子串长度一直增加,直到遇到第一个重复字符'a',

如果加入'a',就违反了题目要求,不能有重复字符,因此我们需要做一些处理。这个时候,当前子串subStr的值为"dabc",因为

重复的字符是'a',子串的基本要求是连续的,如果我们需要继续往下读并加入新的字符,就需要丢弃当前子串subStr中的重复字符

以及排在它之前的所有字符,在本例中需要丢弃subStr中字符'a'本身及其之前的字符'd',此时subStr的值变为"bc",这样我们就可以

用截取后的subStr接上重复字符'a',继续往下读取和计算。

有了上面这种思路后,我们需要更深入地考虑细节处理。

首先定义一些变量用来解题,int max, cur,max用于记录最大子串长度,cur用于记录当前子串的长度。

map<char, int> hashMap用于记录当前子串subStr中已有的字符,及该字符在子串中的位置,位置是以0开始的。

有了以上变量,解法如下:

每次读取原字符串S中的一个字符,有2种情况:

1.如果这个字符在hashMap中没有记录,则说明字符在subStr中不存在,我们可以将该字符加入subStr,并

     在hashMap中记录这个字符及其在subStr中的位置。++cur,如果此时cur > max,max = cur。

2.如果这个字符在hashMap中存在记录,说明字符出现了重复,我们在hashMap中找到这个字符在subStr中的位置,

   将这个字符之前的所有字符在hashMap中的记录删除,将这个字符之后的所有字符的位置修改,最后修改这个字符

   在subStr中的位置。例子"dabcabc"中,subStr值为"dabc",下一个读取的字符为'a',则删除de的记录,b的位置

   记录由2变为0,c的由3变为1,而最后修改的a因为接在"bc"之后,a的位置由1变为2。处理完hashMap,接下来再

    改变subStr和cur的值即可。由于截取字串后,cur <= max,所以这里的max值不会得到修改。

 

以下是我写的代码,欢迎各位大牛指导交流~

AC,Runtime: 164 ms

//LeetCode_Longest Substring Without Repeating Characters
//Written by zhou
//2013.11.2

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
        
        map<char,int> hashMap;  //用于记录当前子串中已有的字符,及字符在子串中的位置
        map<char,int>::iterator it;
        string subStr = "";
        int max = 0, cur = 0;
        for (int i = 0; i < s.length(); ++i)
        {
            it = hashMap.find(s[i]);
            if (it == hashMap.end())  //map中没有此字符
            {
                subStr += s[i];
                ++cur;
                hashMap.insert(std::pair<int,int>(s[i],cur - 1));
                if (cur > max)
                   max = cur;
            }
            else   //map中存在此字符
            {
                int pos = it->second;
                
                //删除子串中在重复字符之前的所有字符记录
                for (int j = 0; j < pos; ++j)
                {
					hashMap.erase(subStr[j]);
                }
                
                //修改子串中在重复字符之后的所有字符位置
				for (int j = pos + 1; j < subStr.size(); ++j)
				{
					hashMap[subStr[j]] = hashMap[subStr[j]] - (pos + 1);
				}
				
				//修改子串及cur记数
				subStr = subStr.substr(pos + 1) + s[i];
                cur = cur - (pos + 1) + 1;
                
                //修改重复字符在子串中的位置记录
				hashMap[s[i]] = cur - 1;
            }
        }
        return max;
    }
};


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值