这道题用的方法是在LeetCode中很常用的方法,对于字符串的题目非常有用。 首先brute force的时间复杂度是O(n^3), 对每个substring都看看是不是有重复的字符,找出其中最长的,复杂度非常高。优化一些的思路是稍微动态规划一下,每次定一个起点,然后从起点走到有重复字符位置,过程用一个HashSet维护当前字符集,认为是constant操作,这样算法要进行两层循环,复杂度是O(n^2)。
最后,我们介绍一种线性的算法,也是这类题目最常见的方法。基本思路是维护一个窗口,每次关注窗口中的字符串,在每次判断中,左窗口和右窗口选择其一向前移动。同样是维护一个HashSet, 正常情况下移动右窗口,如果没有出现重复则继续移动右窗口,如果发现重复字符,则说明当前窗口中的串已经不满足要求,继续移动有窗口不可能得到更好的结果,此时移动左窗口,直到不再有重复字符为止,中间跳过的这些串中不会有更好的结果,因为他们不是重复就是更短。因为左窗口和右窗口都只向前,所以两个窗口都对每个元素访问不超过一遍,因此时间复杂度为O(2*n)=O(n),是线性算法。空间复杂度为HashSet的size,也是O(n). 代码如下:
public int lengthOfLongestSubstring(String s) { if(s==null || s.length()==0) return 0; HashSet<Character> set = new HashSet<Character>(); int max = 0; int walker = 0; int runner = 0; while(runner<s.length()) { if(set.contains(s.charAt(runner))) { if(max<runner-walker) { max = runner-walker; } while(s.charAt(walker)!=s.charAt(runner)) { set.remove(s.charAt(walker)); walker++; } walker++; } else { set.add(s.charAt(runner)); } runner++; } max = Math.max(max,runner-walker); return max; }这道题思想在字符串处理的题中还是比较重要的,实现上主要是HashSet和数组index的操作。扩展的题目有Substring with Concatenation of All Words,Minimum Window Substring,思路是非常接近的,只是操作上会更加繁琐一些。
上次google mock interview面的跟这个很像。是返回最长的字母相同的substring
回复删除那个应该比这道题简单,不需要维护hashset,只要一遍扫过去记录最长的重复串就可以。
删除求问哪里写错了,leedcode给的expected结果不对啊。
回复删除public class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null){
return 0;
}
String temp = "";
String res = "";
for (int i=0; i res.length()){
res = temp;
}
temp = "" + s.charAt(i);
}
}
return res.length();
}
}
你试一下这个测试例子“abcad"就知道问题在哪里了~
删除此评论已被作者删除。
回复删除代码贴的有遗漏啊,总体就是遍历一遍s,比较每个char,如果temp有没有这个char就存入char,如果有的话,就比较temp和res长度,temp长度大的话就换res,temp存入当前重复的那个char。再进行下一轮
回复删除前面说错了,如果temp没有这个char就存入这个temp
删除对于Minimum Window Substring,我贴下题目Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
回复删除For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC".
例子里输出时BANC,这里不是所有char是T里的啊。。题目里window没明白
只要包含所有T里面的字符就可以
删除