Leetcode題目總結[3]無重複字元的最長字串
1.題目描述
給定一個字串s
,請你找出其中不含有重複字元的最長子串的長度。
示例1:
輸入: s = "abcabcbb"
輸出: 3
解釋: 因為無重複字元的最長子串是 "abc",所以其
長度為 3。
示例 2:
輸入: s = "bbbbb"
輸出: 1
解釋: 因為無重複字元的最長子串是 "b"
,所以其長度為 1。
示例 3:
輸入: s = "pwwkew"
輸出: 3
解釋: 因為無重複字元的最長子串是"wke"
,所以其長度為 3。
請注意,你的答案必須是 子串 的長度,"pwke"
是一個子序列,不是子串。
示例 4:
輸入: s = ""
輸出: 0
提示:
0 <= s.length <= 5 * 104
s
由英文字母、數字、符號和空格組成
2.做法
首先要分清楚子串和子序列
子串:串中任意個連續的字元組成的子序列稱為該串的子串 如:coffee中的offe是一個子串
序列:序列是被排成一列的物件(或事件);這樣每個元素不是在其他元素之前,就是在其他元素之後。這裡,元素之間的順序非常重要
子序列:子序列就是在原來序列中找出一部分組成的序列 如:coffee中的ofe可以是一個子序列,而不可以是一個子串
一開始啥想法都沒有,瞄了一眼題解,滑動視窗+hashmap?
看了一會迷迷糊糊地也沒怎麼看懂 但是到自己真動手寫的時候就知道為什麼是滑動視窗+hashmap了
最暴力的做法就是枚舉出所有區間並判斷區間內是否有重複字元 並找出符合條件的最長區間
一共有Σ? 好吧算不出來總之就是很多個不合法區間
我們可以利用兩個指標組成一個滑動視窗,從左往右移動視窗,每次右指標右移一位,加入一個字元,並判斷現在的字串裡有沒有與新字元相同的字元,如果有,則加入這個新字元以後的子串不合法。
我們可以記錄一下沒加入新字元時的字串長度,
然後將左指標右移繼續計算下面的字串
當所有的可能的合法區間都列舉並計算一遍後即可得到答案
判斷:這裡我是直接迴圈區間挨個字元判斷,不知道有沒有其他做法 比如利用hash表中存的字元出現的最後位置與指標位置比較直接判斷之類的?(臨時想法也沒有試過也許有點得不償失?)
左指標右移:一開始我以為只是單純右移一位就可以了(只考慮了樣例1的情況),但是右移之後遇到同樣的字元會出問題(卡了樣例3) 記錄完pw子串的長度後 這個p就沒有用了 因為以這個p開頭的子串最長只能到這裡,所以我們可以在記錄完子串長度後就將這個p廢棄掉, pw中的w也是,假如你說兩個重複w直接可能還有其它合法字元,但是在遇到第二個w之後,以第一個w開頭的子串最長也就到第二個子串為止,而以第一個w後面的字元開頭的子串可能還會更長,所以我們可以捨棄掉第一個w,可以直接將左指標跳到第一個w+1的位置。於是我們用hash記錄每個字元對應的最後出現的位置,在左指標右移時直接移動到對應位置+1就可以了。c++我用的不熟,就用陣列暫時代替了
3.程式碼
C++:
1 /* 2 * @lc app=leetcode.cn id=3 lang=cpp 3 * 4 * [3] 無重複字元的最長子串 5 */ 6 7 // @lc code=start 8 class Solution { 9 public: 10 int lengthOfLongestSubstring(string s) { 11 int len = s.length(); 12 int maxans = 0; 13 int start = 0,flag = 0; 14 int temp; 15 int a[500]= {}; 16 if(len == 0) return 0; 17 for(int i = 0; i < len; i++) 18 { 19 20 for(int j = start; j < i; j++) 21 { 22 if(s[j] == s[i]) 23 { 24 flag = 1; 25 temp = a[s[i] - ' '] + 1; 26 break; 27 } 28 } 29 if(flag == 1) 30 { 31 start = temp; 32 } 33 maxans = max(maxans,i - start + 1); 34 flag = 0; 35 a[s[i] - ' '] = i; 36 } 37 return maxans; 38 } 39 }; 40 // @lc code=end
4.做題時遇到的錯誤
runtime error: index -65 out of bounds for type ‘int [26]’
錯誤原因是陣列越界
因為題目沒有限制字元一定是26個英文字母,也可能有'-' ' ' '?' '!' '*'等符號
在建立hash表的時候要將表的範圍擴大一點
我將表的範圍擴到了500就可以了 (隨便選的數字)