字節跳動面試--三面算法題覆盤

題目描述:

查找字符串中給定的連續不重複序列

給定如下不重複序列和一個字符串,請返回不重複序列連續出現在字符串中第一個字母的位置。
例如
給定不重複序列[a,b,c,d]
字符串adcebadcb
則返回4

解題思路:

個人以爲,此題的解題關鍵在於如何去判斷一個字符在不在給定序列中?如果在的話,重複出現了又該如何處理?

備戰面試刷題的經驗告訴我,這裏可用到一個特殊的哈希表來處理上述兩個問題。

我們可以定義一個長度爲256的int數組來當作我們的哈希表,長度爲什麼是256?因爲ASCII碼!我們可以用字符的ASCII碼來直接索引定位到該字符。

下面是我個人的解題思路。首先要把哈希表初始化,把序列中存在的字符全部置1,否則置0。然後開始用一個兩層嵌套的while循環,第一層循環用來移動下標,第二層則用來標識當前連續的合法字符個數,當個數等於序列長度並且全部合法時即求得解。

還是要嘮叨一下哈希表的使用問題,在第二層循環裏,我們用到哈希表來判斷字符的合法性,當前字符在哈希表中的值爲0則說明該字符不合法。若一個合法字符重複出現的話,我們該怎麼處理呢?這裏,考慮到序列中不重複,每當我們遇到一個合法字符,我們就把該字符在哈希表中的值改爲0,也就是後續再重複出現的話,他就成爲了不合法字符。(這種做法會產生一個問題,就是我們更改了哈希表,所以我們要在每次進入第二層循環之前,重新初始化哈希表。)

後續:

你以爲我應該在這裏放代碼了?我偏不!與二面一樣,面試官又給我加了進階版的題目。

如果將不重複序列改成可能重複的序列要怎麼解決?
例如
可重複序列[a,b,c,d,b]
字符串adcebdbcbadcbd
返回5

這裏我就不多說了,經過思考,我發現只要更改掉上面的哈希使用方法即可適配這個進階版題目。也就是把置0和置1操作變成,在初始化的時候全置0後再加1(不是直接置1),判斷合法性的時候是減1(不是直接置0)。你品,你細細的品!

 

我的做法還有優化的空間,我目前的優化思路是在下標移動上做一些文章,比如,當一個不存在於序列中的字符e出現了,這個時候我們直接把下標移動到e的後面,而不是簡單的在a的位置基礎上加1。(然而我並沒有去實現這個需求)

如果大佬們還有更好的辦法,請帶帶我這個菜雞!

嘮叨太多了,下面放代碼吧!

C++代碼:

這裏放的代碼是兼容上面兩問的。

#include <iostream>
#include <vector>
#include <string>

using namespace std;

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

static int hash[256];

inline void CleanHash(vector<char> set){//重置哈希表 
	for(int i = 0; i < 256; ++i){
		hash[i] = 0;
	}
	for(int i = 0; i < set.size(); ++i){
		hash[set[i]]++;
	}
}
int Find(vector<char> set, string str){
	if(str.length() < set.size()) return -1; //處理特殊情況
	int num = 0;//記錄當前連續合法字符長度 
	int index = 0; //記錄下標位置 
	while(index <= (str.length() - set.size())){
		//cout << index << endl;
		CleanHash(set);
		num = 0;
		while(num < set.size()){//合法性判斷
			if(hash[str[index]] != 0){
				hash[str[index]]--;
				index++;
				num++;
			}
			else{
				break;
			}
		}
		if(num == set.size()) return index - num;
		
		index -= num-1;//此處可優化
	} 
	return -1;
}
int main(int argc, char** argv) {
	vector<char> set;
	set.push_back('a');
	set.push_back('d');
	set.push_back('c');
	set.push_back('b');
	set.push_back('b');
	string str("adcebdbcbadcbd");
	cout << Find(set,str);
	return 0;
}

 

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