散列

問題:給出N個正整數,再給出M個正整數,問這M個數中每個數分別是否再N個數中出現過,其中N,M\leq10^{5}.

最直接的思路是:對每個欲查詢的正整數x,遍歷所有N個數,看是否有一個數與x相等。這個做法的時間複雜度爲0(NM),當N和M很大時,這個方法肯定不行了。

有一個新思路——用空間換時間,設定一個bool型數組hashTable[100010],其中hashTable[x]==true表示正整數x在N個正整數中出現過,而hashTable[x]==false表示正整數x在N個正整數中沒有出現過。這樣就可以在讀入N個正整數可以預處理,即當讀入數爲x時,令hashTable[x]==true(說明:hashTable數組需要初始化爲false,表示初始狀態下所有數都未出現過)。於是對M個數欲查詢的數,就能直接通過hashTable數組判斷每個數是否出現過。這種方法的時間複雜度O(N+M)。

例如:N個整數爲{8,3,7,6,2},欲查詢的M個整數爲{7,4,2}。

#include<cstdio>
const int maxn=10010;
bool hashTable[maxn]={false};//初始化
int main()
{
	int n,m,x;
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&x);
		hashTable[x]=true;//數字X出現過 
	}
	for(int i=0;i<m;i++)
	{
		scanf("%d",&x);
		if(hashTable[x]==true)//如果數字X出現過則輸出YES 
		{
			printf("YES!\n");
		}
		else{
			printf("NO!\n");
		}
	}
	return 0;
} 

如果題目要求M個欲查詢的數中每個數在N個數中出現的次數,那麼可以把hashTable數組替換爲int型,然後再輸入N個數時進行預處理,即當輸入數爲x時,就令hashTable[x]++,這樣就可以用O(N+M)的時間複雜度輸出每個欲查詢的數出現的次數。

#include<cstdio>
const int maxn=10010;
bool hashTable[maxn]={0};//初始化
int main()
{
	int n,m,x;
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&x);
		hashTable[x]++;//數字X出現過 
	}
	for(int i=0;i<m;i++)
	{
		scanf("%d",&x);
		printf("%d\n",hashTable[x]); 
	}
	return 0;
} 

以上兩個方法雖然好,也只能解決一部分這方面問題,如果輸入的數非常大呢(十的九次方以上),如果輸入的是一個字符串呢,就不能直接將輸入的內容作爲數組下標了。這就引出了散列(hash)

散列可以濃縮成一句話“將元素通過一個函數轉換爲整數,使得該整數可以儘量唯一地代表這個元素”。其中把這個轉換函數稱爲散列函數H,也就是說,如果元素在轉換前爲key,那麼轉換後就是一個整數H(key)。

 

發佈了125 篇原創文章 · 獲贊 2 · 訪問量 3978
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章