题目:给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
本来想整个滑动窗口,但是因为各种特殊情况,就一直不对,最好的滑动窗口的版本如下:
public class Solution
{
public int LengthOfLongestSubstring(string s)
{
char[] sChar = s.ToCharArray();//将字符串变为字符型数组
int Window = 0; //定义滑动窗口
int MaxLength = 0; //定义最长不重复字符串长度
char[] LongestStr = new char[sChar.Length];
//确定窗口大小(字符串中一共有多少个不同字符)
for(int i = 0;i<sChar.Length;i++)
{
if(Array.IndexOf(LongestStr,sChar[i])<0)
{
LongestStr[Window] = sChar[i];
Window++;
}
}
//求最大长度
for(int j=0;j<(sChar.Length-Window+1);j++)
{
char[] ResStr = new char[sChar.Length];
int Length = 0;
for (int m=0;m<Window;m++)
{
if(Array.IndexOf(ResStr,sChar[j+m])<0)
{
Length++;
ResStr[Length-1]=sChar[j+m];
}
else break;
}
if(Length>=MaxLength)
{
MaxLength = Length;
}
}
return MaxLength;
}
}
但即便这样,还是没能通过所有的测试用例
然后发现思路的确有问题,就是滑动窗口还是不能遍历所有的情况
于是,开始想别的方法🤔
既然滑动窗口会漏掉情况,就想干脆就不要滑动了,改变窗口大小
public class Solution
{
public int LengthOfLongestSubstring(string s){
char[] sChar = s.ToCharArray();//将字符串变为字符型数组
int MaxLength=0;
for (int i=0;i<sChar.Length;i++)
{
int Length = 0;
char[] ResStr = new char[sChar.Length];
for(int j=0;i+j<sChar.Length;j++)
{
if(Array.IndexOf(ResStr,sChar[i+j])<0)
{
Length++;
ResStr[Length-1]=sChar[i+j];
}
else break;
}
if(Length>=MaxLength)
{
MaxLength = Length;
Length = 0;
}
}
return MaxLength;
}
}
思路很简单粗暴:
但是没想到,这次又变了个花样得不过:
看来大力不能出奇迹🤔 不能牺牲时间来保全情况完整
挣扎了很久之后,最终,我还是借鉴了前辈的经验,原来代码可以很简洁😂
public class Solution
{
public int LengthOfLongestSubstring(string s){
int i = 0;
int j = 0;
int maxLength=0;
char[] cs = s.ToCharArray();
int n = s.Length;
HashSet<char> cSet = new HashSet<char>();
while (i < n && j < n)
{
if (!cSet.Contains(cs[j]))
{
cSet.Add(cs[j]);
j++;
maxLength = Math.Max(maxLength, j - i);
}
else
{
cSet.Remove(cs[i]);
i++;
}
}
return maxLength;
}
}
HashSet是一个散列表,里头用于存储不重复的值
i和j相当于两个指针,分别指向窗口的头和尾,通过改变i和j指向来滑动窗口
当没有遇到重复值的时候,就往cset中存入值,并移动j;当遇到重复值的时候,就删除cset中i对应的值,并往后移动i
其本质上,就是利用i和j当作一个大小可变的窗口,框出cs中的一段字符串,看这个范围中有没有重复的值,用这样的方式来找出最长不重复子串
重要思路步骤:利用i和j,截取cs字符串中的一段字符
果然该用的东西还是要用起来,指针的思路在这题中就很有用,暴力解决是不行的