面試題48 最長不含重複字元的子字串

2021-10-06 10:01:10 字數 3252 閱讀 7790

題目:請從字串中找出乙個最長的不包含重複字元的子字串,計算該最長子字串的長度。

示例:

示例 1:

輸入: 「abcabcbb」

輸出: 3 【解釋: 因為無重複字元的最長子串是 「abc」,所以其長度為 3。】

示例 2:

輸入: 「bbbbb」

輸出: 1 【解釋: 因為無重複字元的最長子串是 「b」,所以其長度為 1。】

示例 3:

輸入: 「pwwkew」

輸出: 3 【解釋: 因為無重複字元的最長子串是 「wke」,所以其長度為 3。請注意,你的答案必須是子串的長度,「pwke」 是乙個子串行,不是子串。】

求最長子串,是乙個最優解問題,那麼首先應該想到動態規劃,借助輔助陣列空間得到結果。我想到了動態規劃,但陣列中儲存的元素我想錯了,我拿陣列每次儲存字元了,然後寫出來就是暴力法了?。這個帶有一點動態規劃的暴力法思想是這樣的:利用輔助陣列得到了所有子串,儲存最大子串的長度,最後返回即可。

那我們那舉個例子,畫圖理解過程,輸入: 「pwwkew」 輸出: 3

是否重複和重複的兩種結果,我們通過index的值來表示,當不重複,那麼index的值不變,直接index++,即可儲存下乙個元素;如果重複,不是最後乙個元素,j為重複元素的下標,刪除0~j,index需要變化,index-=(j+1),指向刪除後陣列的最後乙個元素,再index++,儲存元素;如果是最後乙個,那麼index=-1,表示陣列沒有元素,然後index++,把元素儲存到0號下標。

我們給出**:

int

lengthoflongestsubstring

(string s)

else

//存在重複,如果重複的數值是陣列最後一位,那麼陣列從頭開始存,否則刪除重複下標前的資料即可,陣列繼續從後儲存

else

//不是最後一位

index-

=(j+1)

;}break;}

} index++

;//陣列下標++

dp[index]

=s[i];}

max=

(index+1)

>max?

(index+1)

:max;

//需要判斷最後一次的子串是否是最長的

return max;

}

這個方法,需要三次迴圈,一次遍歷陣列,一次找重複,一次刪除重複元素之前的數,時間複雜度為o(n^3)極高。

那正確的動態規劃應該是用陣列儲存當前的最長字元長度,而不是字元,即dp[i]表示從0~i位置的最長字元長度,那我們來看一下,如何分析它的初始狀態,轉移方程,返回值。

我們還是用示例:輸入: 「pwwkew」 輸出: 3 來理解過程:

那我們給出**:

//dp陣列儲存i位置最長子串的數字,

intlengthoflongestsubstring

(string s)

else

//雖然重複,但沒有在最長子串中

break;}

}//沒有重複,則直接+1即可

if(flag)

}return max;

}

這個思路,乙個for進行遍歷,乙個for查詢重複,開闢了o(n)的空間。

我們發現這個題目就是不斷地根據 i 和 j 來確定所有子串的長度,每次i-j為子串長度,max儲存最長的。兩個變數,乙個向前遍歷,乙個找重複的。有沒有想到雙指標呢,確實,這個題目也可以拿雙指標解答,它可以節省空間,我們來看一下思路吧:

那我們還是用示例:輸入: 「pwwkew」 輸出: 3 來理解過程:

那我們給出**:

int

lengthoflongestsubstring

(string s)}if

(flag)

//沒有重複元素,視窗擴大

}return max;

}

還是迴圈了兩邊,那有沒有什麼解決辦法,一次性就找到重複元素的位置,那我們會想到陣列,雜湊表,即陣列下標表示元素,陣列儲存出現位置,那我們下面看看。

我們可以利用雜湊表,因為它可以儲存鍵值和數值,我們可以省去迴圈找重複這乙個迴圈,那麼思路是什麼呢,其實主要思想沒變,就是少了迴圈的:

那我們還是用示例:輸入: 「pwwkew」 輸出: 3 來理解過程:

那我們給出**:

//4.引入雜湊表,上面雙指標我們的時間複雜度,第一次for是遍歷,第二次是判斷重複,那麼我們可以引入雜湊,直接得到重複陣列的下標,對滑動視窗的值,進行改變

intlengthoflongestsubstring

(string s)

hash[s[right]

]=right;

//更新資料最後一次出現的位置

res=

max(right-left+

1,res)

;//1-0為1,包含0,1兩個元素

}return res;

}

因為是字串,那麼我們也可以用陣列進行儲存,思路更簡單,雙指標原理不變,就容器變了:

這個過程和上面一樣,那就直接看一下**吧:

int

lengthoflongestsubstring

(string s)

a[s[right]

]=right;

res=

max(right-left+

1,res);}

return res;

}int

main()

加油哦!?。

面試題48 最長不含重複字元的子字串

請從字串中找出乙個最長的不包含重複字元的子字串,計算該最長子字串的長度。假設字串中只包含a z的字元。例如,在字串 arabcacfr 中,最長的不含重複字元的子字串是 acfr 長度為4。我們定義函式f i 表示以第i個字元為結尾的,不包含重複字元的子字串的最長長度。我們從左到右逐一掃瞄字串中的每...

面試題48 最長不含重複字元的子字串

題目描述 請從字串中找出乙個最長的不包含重複字元的子字串,計算該最長子字串的長度。示例 1 輸入 abcabcbb 輸出 3 解釋 因為無重複字元的最長子串是 abc 所以其長度為 3。示例 2 輸入 bbbbb 輸出 1 解釋 因為無重複字元的最長子串是 b 所以其長度為 1。示例 3 輸入 pw...

面試題48 最長不含重複字元的子字串(C )

請從字串中找出乙個最長的不包含重複字元的子字串,計算該最長子字串的長度。示例 1 輸入 abcabcbb 輸出 3 解釋 因為無重複字元的最長子串是 abc 所以其長度為 3。示例 2 輸入 bbbbb 輸出 1 解釋 因為無重複字元的最長子串是 b 所以其長度為 1。示例 3 輸入 pwwkew ...