[LeetCode] Longest Substring Without Repeating Characters 解題報告

—— write for my baby, mua


[題目]

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.


[中文翻譯]

給定一個字符串,求沒有重複字母的最長子串的長度。

例子:

給定 "abcabcbb",最長子串爲 "abc",長度爲3。

給定 "bbbbb",最長子串爲 "b",長度爲1。

給定 "pwwkew",最長子串爲 "wke",長度爲3。注意,結果必須爲子串,"pwke"是一個子序列而不是子串。


[解題思路]

O(N)

設字符串S下標i處的字母S[i]=A,那麼以S[i]作結尾的沒有重複字母的最長子串,受兩個因素影響。

1. S[i]=A,A上一次出現的位置a

2. 所有已經出現的重複的字母對···B···B···、···C···C···、···,第一個字母中離S[i]最近的一個的位置,即max(B,C,···)=b

第一條很自然,因爲出現了重複的A,那麼子串最長只能是[a+1,i]。

第二條的原因是,子串[a+1,i]中,可能已經出現過重複的字母,而影響最長子串的,是所有已經出現的重複字母對中,第一個字母離S[i]最近的位置b,顯然子串最長只能是[b+1,i]

綜合1、2,沒有重複字母的最長子串,只能是在[a+1,i]和[b+1,i]中取短的。


線性地遍歷整個字符串,可以用一個數組int prePosition[128]記錄每個字母上一次出現的位置,初始值設爲-1,用一個整數int startBound記錄最近出現重複字母對中第一個字母的位置,初始值設爲-1。

在考慮S[i]作結尾的最長子串時,長度即爲min(i-prePosition[S[i]], i-startBound)

考慮完S[i],如果prePosition[S[i]]>startBound,則更新startBound,因爲出現了位置更近的重複的字母對中的第一個字母;然後再更新prePosition[S[i]]=i,因爲在考慮S[i+1]時,上一次出現S[i]的位置已經變爲了i。



[C++代碼]

class Solution {
public:
	int prePosition[128];

	void initPrePosition() {
		for (int i = 0; i < 128; i++)
			prePosition[i] = -1;
	}

	int lengthOfLongestSubstring(string s) {
		int max = 0;
		int startBound = -1;

		initPrePosition();

		for (int i = 0; i < s.length(); i++) {
			int prePos = prePosition[(int)s.at(i)];
			int len;

			if (prePos > startBound)
				len = i - prePos;
			else
				len = i - startBound;

			if (len > max)
				max = len;

			if (prePos > startBound)
				startBound = prePos;

			prePosition[(int)s.at(i)] = i;
		}

		return max;
	}
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章