leetcode-3-Longest Substring Without Repeating Characters
题目:Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb"
, the answer is "abc"
, which the length is 3.
Given "bbbbb"
, the answer is "b"
, with the length of 1.
Given "pwwkew"
, the answer is "wke"
, with the length of 3. Note that the answer must be a substring, "pwke"
is a subsequence and not a substring.
思路:这个题之前在nowcoder上做过。要求找出不重复的最长子串,我的方法是构造一个滑动窗口记录最长不重复子串的左右位置,左窗口left最初为0,用max来记录过程中的最长不重复子串的长度,只要当前字符未在之前出现过,则left保持和之前一样的值,遍历指针i就一直往后移,则当前的最长长度就为max=max(max,i-left+1),如果当前字符在前面字符重复了,则放弃前面那个字符的位置,即让left=前面那个重复的字符的位置的下一个位置(即放弃前面那个字符选这个字符);对于字符的判重,我的做法是利用HashMap来记录,在遍历整个字符串的同时,将首次出现的字符放入HashMap中,其同样字符再次出现时,便可以判重了,对于重复了的字符由于要将前面的那个舍去,所以,继续将其放入HashMap中
实现代码如下:
1 import java.util.HashMap; 2 class Solution { 3 public int lengthOfLongestSubstring(String s) { 4 if(s==null) return 0; 5 HashMap<Character,Integer>map=new HashMap<>(); 6 int left=0;//左窗口最初位置 7 int max=0;//全局最长长度 8 for(int i=0;i<s.length();i++){ 9 char c=s.charAt(i); 10 left=Math.max(left,map.containsKey(c)?map.get(c)+1:0); 11 max=Math.max(max,i-left+1); 12 map.put(c,i); 13 } 14 return max; 15 } 16 17 }
显然,我这种算法由于额外借用HashMap,所以实现速度明显不高,学习了下排名第2的算法
1 class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 int n = s.length(), ans = 0; 4 int[] index = new int[128]; 5 for(int j=0, i=0; j<n; j++){ 6 i = Math.max(index[s.charAt(j)], i); 7 ans = Math.max(ans, j-i+1); 8 index[s.charAt(j)] = j+1; 9 } 10 return ans; 11 } 12 }
来看一下他的这种算法,他是利用了类似于桶排序的思路来记录每个字符的位置,实现方法很巧妙
int[] index = new int[128];
index[s.charAt(j)] = j+1;
用index数组来记录每个字符后面的位置,数组初始化为0,每遍历一个字符就将该字符后面的位置记录下来,只要后面该字符再次出现,则数组中该字符所对应的值就意为放弃前面这个字符后的下一个位置
i = Math.max(index[s.charAt(j)], i);
这里的i就相当于我的方法里的左窗口left
当字符未重复时,index数组初始为0,此时i=i,即左窗口不变化
当字符有重复时i=index[s.charAt(j)],此时的i就相当于放弃了前一个重复字符,选后一个
ans = Math.max(ans, j-i+1);
这句话很好理解,就是更新过程中的最大值
真的是很巧妙!