给定一个字符串,找出不含有重复字符的最长子串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 无重复字符的最长子串是 "abc",其长度为 3。
解法1
建立一个256位的整型数组,因为ASCII表能表示256位字符,这样我们可以记录所有的字符,然后定义两个变量res和left,res用来记录最长无重复子串的长度,left记录该无重复子串左边的起始位置,然后我们遍历整个字符串,对于每一个遍历的字符,如果数组中的值为0,表示之前还没遇到该字符,此时需要计算最长无重复子串,即最右边减去最左边的长度(i-left+1),i表示最右边,left表示最左边
还有一种情况也要考虑,由于此时出现重复的字符,left的位置也更新了,如果又遇到该字符,需要重新计算最长无重复子串.
static int LengthOfLongestSubstring1(string s)
{
int[] m = new int[256];
for (int i = 0; i < m.Length; i++)
{
m[i] = 0;
}
int res = 0, left = 0;
for (int i = 0; i < s.Length; i++)
{
if (m[s[i]] == 0 || m[s[i]] < left)
{
res = Math.Max(res, i + 1 - left);
}
else
{
left = m[s[i]];
}
m[s[i]] = i + 1;
}
return res;
}
解法2
简化解法1的操作
static int LengthOfLongestSubstring2(string s)
{
int[] m = new int[256];
for (int i = 0; i < m.Length; i++)
{
m[i] = 0;
}
int res = 0, left = 0;
for (int i = 0; i < s.Length; i++)
{
//当m[s[i]]不为0,说明该字符已经出现过了,可能需要变化left的位置了
left = Math.Max(left, m[s[i]]);
m[s[i]] = i + 1;
//i+1-left:表示的是最右边的减去最左边的长度
res = Math.Max(res, i + 1 - left);
}
return res;
}
解法3
使用HashSet来表示,把出现的字符存放到set中,遇到set中没有出现过的,加入到set中,并更新res的值,如果遇到重复的了,则从左边开始删字符,直到删除到重复的字符停止
static int LengthOfLongestSubstring3(string s)
{
int res=0,left=0,right=0;
HashSet<int> set=new HashSet<int>();
while(right<s.Length)
{
if(!set.Contains(s[right]))
{
set.Add(s[right++]);
res=Math.Max(res,set.Count);
}
else
set.Remove(s[left++]);
}
return res;
}