1. 程式人生 > >leetcode-3-Longest Substring Without Repeating Characters

leetcode-3-Longest Substring Without Repeating Characters

思路 charat clas repeat hat 桶排序 left ger lee

題目: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);

這句話很好理解,就是更新過程中的最大值

真的是很巧妙!

leetcode-3-Longest Substring Without Repeating Characters