符串的最長無重複字符的子串長度


題目描述:算法


對於一個字符串,請設計一個高效算法,找到字符串的最長無重複字符的子串長度。ide

給定一個字符串A及它的長度n,請返回它的最長無重複字符子串長度。保證A中字符所有爲小寫英文字符,且長度小於等於500。函數

測試樣例:測試

"abcdbefgdchi",12
返回:8

這個題我研究了好半天,確實很差想,看了別人的思路,半天才把代碼寫出來j_0016.gifspa


分析:設計


首先定義三個輔助變量:orm

max_len:表示字符串中最長無重複字符的子串長度,也就是函數返回blog

map<char, int>:用來存放當字符串前位置的字符最近出現的位置字符串

pre_len:用來存放當前位置以前最長無重複字符的子串長度string


下面開始主邏輯


從字符串的起始處開始遍歷

若是map中沒有該字符,則將該字符及其下標插入到map中,並將pre_len++

再和max_len進行比較,取較大者賦給max_len

若是map中已經有了該字符,那麼取出該字符對應的值(也就是該字符最近出現的下標)記爲pos_A

當前下標減去pre_len記爲pos_B,表示前面最長無重複字符子串的起始位置

wKioL1fJsh3DEllGAAASyVr7rFU895.jpg

這時候,pos_A和pos_B會有一下三種狀況:

第一種狀況:posA == pos_B

第二種狀況:pos_A > pos_B

第三種狀況:pos_A < pos_B


對於第一種狀況來講,pre_len 大小不會改變。

對於第二種狀況來講,pos_A 在 pos_B的右邊,根據 pos_A 和 pos_B 所表明的含義可知道:

在距離當前很近的位置上,當前字符已經出現了重複,所以當前位置以前最長無重複字符子串的長度縮短了,如圖所示:


wKiom1fJr8jibAFqAAAXblUWguI179.jpg

所以,更新後的 pre_len 應該爲 當前位置的下標減去 pos_A

 

對於第三種狀況來講,pos_A 在 pos_B 的左邊,根據 pos_A 和 pos_B 所表明的含義可知道:

在距離當前很遠的位置上,當前字符出現了重複,這個位置比pos_B 還遠,這麼遠的路徑上,pos_B 處的字符早已出現了重複,所以當前位置以前最長無重複字符子串的長度應該爲 當前位置到pos_A 的距離,如圖所示


wKiom1fJsmHyZdMKAAAV8sU32hM819.jpg


所以,更新後的 pre_len 應該爲 當前位置的下標減去 pos_B + 1

更新後的pre_len 與max_len 進行比較,取其大者便可


注意,最後應該將map中當前位置字符的下標進行更新(千萬不能漏掉)



因而乎一個完整的邏輯已經完成了,這樣從頭至尾遍歷這個字符串,最終即可獲得

字符串的最長無重複字符的子串長度 max_len


甚至還能夠得到該字串,將其單獨打印出來(這裏留給讀者自行實現,不難)


代碼以下:

int longestSubstring(string A, int n) {
	if (A.size() <= 0 || n <= 0)
		return 0;

	int max_len = -1;
	int pre_len = 0;
	map<char, int> m;
	for (int i = 0; i < A.size(); ++i){
		if (m.count(A[i]) == 0){
			m.insert(pair<char, int>(A[i], i)); //map中不存在該字符,則直接插入
			++pre_len;
			if (pre_len > max_len)
				max_len = pre_len;
			continue;
		}
	
		map<char, int>::iterator iter_prev = m.find(A[i]);
		int pos_A = iter_prev->second;
		int pos_B = i - pre_len;
		
		if (pos_A > pos_B)
		{
			pre_len = i - pos_A;
		}
		else if (pos_B > pos_A)  //pos_A <= pos_B
		{
			pre_len = i - pos_B + 1;
		}
		else
		{
			//do nothing!
		}

		if (pre_len > max_len)
			max_len = pre_len;

		m[A[i]] = i;  //更新map
	}

	return max_len;
}


j_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gif

如今是 2016.9.3/1:30 時候不早了,睡覺了,晚安!

j_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gifj_0070.gif

相關文章
相關標籤/搜索