Longest Substring Without Repeating Characters (LeetCode)

问题描述: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.

1.O(n)解法

本题可采用动态规划的方法。使用两个指针i,j,分别指向当前非重复子串的串头和串尾。未出现重复的字符时,i指向串头位置不变,j逐渐向原始字符串的尾部移动。当出现一个重复的字符时,说明(s[i],s[j-1])的子串可能是一个最大非重复子串,所以可能需要更新最大值。同时max记录的是所有以(s[0],s[i])开头的最大非重复子串的长度,所以需找下一个最大非重复子串的时候可以把首指针i移动到i+1位置。

因为i,j都只需要遍历字符串一次,所以最坏的情况是2n(当字符串只包含一个字符时),所以运行时间是O(n)。

源代码如下:LeetCode测试时间20ms

class Solution {
public:
	int lengthOfLongestSubstring(string s) {
		int n = s.length();
		int i = 0, j = 0;//i:substring首;j:substring尾
		int maxLen = 0;
		bool exist[256] = { false };
		while (j < n)
		{
			if (exist[s[j]]) //如果已经字符已经扫描过
			{
				maxLen = (maxLen> j - i) ? maxLen : (j - i);
				while (s[i] != s[j])//扫描与s[j]字符相同的字符位置,将首指针移到该位置的下一个字符
				{
					exist[s[i]] = false;
					i++;
				}
				i++;
				j++;
			}
			else
			{
				exist[s[j]] = true;
				j++;
			}
		}
		maxLen = (maxLen > j - i) ? maxLen : (j - i);//将最终扫描结果赋给maxLen
		return maxLen;
	}
};

2.My own solution

自己的方法只用了一个指针,运行时间119ms,很low。
源码如下:
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
    int max = 0;
		int temp = 0;//记录当前非重复子串的长度
		int exclude = -1;//相当于上例的头指针
		map<char, int> mapA;//保存字符串以及最近一次出现的位置
		for (int i = 0; i<s.length(); i++)
		{
			char c = s[i];
			if (mapA.find(c) == mapA.end())//first insert
			{
				mapA[s[i]] = i;
				temp++;
			}
			else//repeating charaters occur
			{
				if (mapA[c] <= exclude)//重复的字符在被排除的字符串里
				{
					mapA[c] = i;
					temp++;
				}
				else
				{
				temp = i - mapA[s[i]];
				exclude = mapA[s[i]];//保存exclude的标签值
				mapA[s[i]] = i;
				}
					
			}
			if (temp > max)
				max = temp;//保存本次子序列的最长非重复字符串长度
		}
		return max;
    }
};

最后分享一篇讲的很好的本题解法(英文)http://leetcode.com/2011/05/longest-substring-without-repeating-characters.html





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值