這個解法是由leetcode上的jack這名用戶上傳,巧妙的使用了哈希表來縮短執行時間,非常值得學習,但是原作者並沒有將原理和亮點講的很清楚,所以我重新將它梳理了一遍發了出來。
思路:
這個解法是以常規的滑動思想爲基礎,字符串左右各一個指針(left和right),左邊的指針標記的是最近的重複字符(初始值爲0.表示暫無重複字符),然後right指針進行遍歷,若遍歷字符與目前兩指針中間的字符串中字符重複,則將left指針移向該重複字符,right指針繼續向前遍歷,知道遍歷結束爲止,其中沒遍歷一個字符,都進行一次目前字符串長度與最長字符串長度的比較。
然後根據字符是由ASCII碼錶示的特點,創建一個256個元素的數組,作爲哈希表,用於儲存每一個字符最近出現位置,若未出現過,則爲0,若出現了,則將其位置信息存入(即right的值),若第二次出現,則通過找到對應ASCII碼值,就可知該字符最近一次出現位置,從而完成left指針的移動。
代碼:
int lengthOfLongestSubstring(char * s){
//用於儲存目前最長字串
int prior = 0;
//用於定位目前不重複字符串的起始字符左邊一個字符(即最近一個出現重複的字符)
int left = 0;
//用數組構建一個哈希表,存儲該字符最近出現位置,若爲0,則表示沒有出現過,並且爲256而不爲128是因爲此處是ASCII擴展字符集
int dict[256] = {0};
//目前所遍歷的字符串的位置
int right = 1;
//存儲目前字符的ASCII值
int i;
while (* s != '\0')
{
//獲得目前字符的ASCII值
i = * s - 0;
//判斷目前所遍歷字符是否出現過
if (dict[i] > left)
//若出現過,則將目前不重複字符串起始位置之前的一位定位到該字符
left = dict[i];
//不論是否出現過,都更新該字母對應哈希表的值
dict[i] = right;
//判斷目前不重複字符串長度是否比出現過的最長不重複字符串長
prior = (prior>right-left)? prior : right-left;
//將指針指向下一個字符
s++;
//更新爲接下來要遍歷的字符的位置
right++;
}
return prior;
}