题目:
给定一个字符串,找出不含有重复字符的最长子串的长度
思路:
建立一个ArrayList<Character>存储加进来的char值。每次加入有两种情况,加入的char原List没有,此时加进list中,并计算长度,与之前储存的长度比较大小,最后当做返回值;第二种情况,加入char原list没有,此时将list中出现此char的索引处以及该处之前的值删去,然后加入该char(画图可知,此时新list长度一定小于等于原list,所以此时不用进行长度的比较)。
贴上代码
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.equals(""))
{
return 0;
}
int n=s.length();
int templen=0;
int maxlen=1;
char [] schar=s.toCharArray();
List<Character> temp =new ArrayList<Character>();
for(int i=0;i<n;i++)
{
if(!temp.contains(schar[i]))
{
temp.add(schar[i]);
if(temp.size()>maxlen)
{
maxlen=temp.size();
}
}
else
{
int first = temp.indexOf(schar[i]);
for(int j=0;j<=first;j++)
{
temp.remove(0);
}
temp.add(schar[i]);
}
}
return maxlen;
}
}
但这有个缺点,很明显时间复杂度为O(n2)乘以indexof方法的复杂度,很容易造成超时。
看答案之后,发现了利用Hashset存取为O(1)的特性来进行划窗法。
其实划窗法思路很类似:
有左指针i,右指针j两个指针,当碰到一个新char值时,hashset存进这个char,然后j++,此时计算j-i值即为hashset中值的个数(然后进行取最大值);当碰到一个老值时,hashset删掉i位置的char值,直到删掉hashset中没有这个char[j]值(其实和之前思路很像,删掉重复值及其之前的所有值)。
代码如下:
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.equals(""))
{
return 0;
}
int n=s.length();
int ans=0,i=0,j=0;
Set<Character> set = new HashSet<Character>();
while(i<n&&j<n)
{
if(!set.contains(s.charAt(j)))
{
set.add(s.charAt(j));
j++;
ans=Math.max(ans,j-i);
}
else
{
set.remove(s.charAt(i));
i++;
}
}
return ans;
}
}