2019/8/3 滑动窗口
class Solution {
public int lengthOfLongestSubstring(String s) {
int [] map = new int[128];
int len = Integer.MIN_VALUE;
int start = 0;
int end = 0;
while(end < s.length()){
int c = s.charAt(end);
if(map[c] == 0){
map[c]++;
if(end - start + 1 >= len){
len = end - start + 1;
}
end++;
}
else{
map[s.charAt(start)] = 0;
start++;
}
}
if(len == Integer.MIN_VALUE) return 0;
return len;
}
}
知识点:
- But look up in hash table should be amortized O(1)O(1) time as long as the hash function was chosen carefully.
- hashmap相交map set hashset,查找速度是最快的
- 滑动窗口 :第一次接触到这个名词是tcp协议那里。就是i,j一头一尾,使j能尽量向右滑动,不满足,则j不动,i删去最左边一个,j继续向右
- 接口的多态:“一个接口,多个类” set=new hashset() set=new treeset就是这个意思。
我这个弱鸡,第一反应总是暴力解法,然后超时gg了
class Solution {
public int lengthOfLongestSubstring(String str) {
char[] longsub=new char[str.length()];
char[] s=str.toCharArray() ;
int k=0,count=0,longcount=0;
for(int m=0;m<str.length()&&(str.length()-m)>=longcount;m++){
char[] sub=new char[str.length()];
sub[0]=s[m];
k=0;
count=1;
for(int i=m+1;i<str.length();i++){
int flag=0;
for(int j=0;j<=k;j++){
if(s[i]==sub[j]){
flag=1;
break;
}
}
if(flag==0){
sub[++k]=s[i];
count++;
System.out.println(count);
System.out.println(s[i]);
}
else{
break;
}
}
if(count>=longcount){
longcount=count;
longsub=sub;
for(int q=0;q<sub.length;q++)
System.out.println("***"+sub[q]);
}
}
return longcount;
}
}
然后换hash表,确实快了,然后testcase又tle gg了
class Solution {
public int lengthOfLongestSubstring(String str) {
char[] longsub=new char[str.length()];
char[] s=str.toCharArray() ;
int k=0,count=0,longcount=0;
for(int m=0;m<str.length()&&(str.length()-m)>=longcount;m++){
// char[] sub=new char[str.length()];
HashMap<String,Integer> sub=new HashMap();
//sub[0]=s[m];
sub.put(String.valueOf(s[m]),0);
k=0;
count=1;
for(int i=m+1;i<str.length();i++){
int flag=0;
if(sub.containsKey(String.valueOf(s[i]))){
flag=1;
break;
}
if(flag==0){
// sub[++k]=s[i];
sub.put(String.valueOf(s[i]),++k);
count++;
System.out.println(count);
System.out.println(s[i]);
}
else{
break;
}
}
if(count>=longcount){
longcount=count;
// longsub=sub;
// for(int q=0;q<sub.length;q++)
// System.out.println("***"+sub[q]);
}
}
return longcount;
}
}
然后我开始看答案了,思路完全是一样的啊,都是两个for循环
hashmap的查找比hashset的还更快,为啥我的还更慢一些呢?
答案1(O(N3)):
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int ans = 0;
for (int i = 0; i < n; i++)
for (int j = i + 1; j <= n; j++)
if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
return ans;
}
public boolean allUnique(String s, int start, int end) {
Set<Character> set = new HashSet<>();
for (int i = start; i < end; i++) {
Character ch = s.charAt(i);
if (set.contains(ch)) return false;
set.add(ch);
}
return true;
}
}
看完答案,想了很久,发现自己代码太冗余了,忘记了character这个数据类型,然后删掉了一些打印的和无意义的代码,答案一跑55ms,我下面这一版只要6ms,开心死了(尽管还是暴力解法,但是我动脑子了啊)
自己的改进暴力解法(时间复杂度为O(N2))如下:
class Solution {
public int lengthOfLongestSubstring(String str) {
char[] longsub=new char[str.length()];
char[] s=str.toCharArray() ;
int k=0,count=0,longcount=0;
for(int m=0;m<str.length()&&(str.length()-m)>=longcount;m++){
HashMap<Character,Integer> sub=new HashMap();
sub.put(s[m],0);
k=0;
count=1;
for(int i=m+1;i<str.length();i++){
int flag=0;
if(sub.containsKey(s[i])){
flag=1;
break;
}
if(flag==0){
sub.put(s[i],++k);
count++;
}
else{
break;
}
}
if(count>=longcount){
longcount=count;
}
}
return longcount;
}
}
再看了答案二(滑动窗口+set),才发现,自己的方法实际上就类似滑动窗口,但是我是用了一个外循环来表示起点,用set更快。如下:
public class Solution {
public int lengthOfLongestSubstring(String s) {
int i=0,j=0,count=0;
Set<Character> set=new HashSet<Character>() ;
while(i<s.length()&&j<s.length()){
if(!set.contains(s.charAt(j))){
set.add(s.charAt(j));
count=Math.max(j-i+1,count);
j++;
}
else{
set.remove(s.charAt(i));
i++;
}
}
return count;
}
}
答案三(优化了的滑动窗口)
虽然我的代码没有标准答案简洁,但是思路更加符合自己的。
public class Solution {
public int lengthOfLongestSubstring(String s) {
int i=0,j=0,count=0;
Map<Character,Integer> map=new HashMap<>() ;
while(i<s.length()&&j<s.length()){
if(!map.containsKey(s.charAt(j))){
map.put(s.charAt(j),j);
}else{
i=Math.max(map.get(s.charAt(j))+1,i);
map.put(s.charAt(j),j);
}
count=Math.max(j-i+1,count);
j++;
}
return count;
}
}