hash的運用

問題爲知道一個數組A[n],和一數字k,存在唯一一對數字A[i] +A[j]= k;

求出這樣的數字的對數,如A{1,2,3,4,5,4,1,6,7}  k=13 求得的結果爲 13=3+7;


首先經好想的方法就是暴力,枚舉任意兩個數字的和 與k比較

for(int i=0;i<n-1;i++)
    for(int j=i+1;j<n;j++)
        if( ( A[i]+A[j] )==k){
             cout<<a[i]<<"  "<<a[j]<<emd;
             break;
        }

但是這不是最好的解法,O(n^2)的時間複雜度有點慢了,

於是想到用hash試試,這裏用set進行求解,

因爲set用紅黑樹實現的,不管是插入還是查找的效率都很可觀的

對數組掃描一遍,(假設已經定義好了 set< int >m)

對於數字A[i] 首先做 m.find(A[i]) 操作,如果反會值爲m.end();

說明集合中還沒有A[i]元素,那麼我們在進行m.find( k-A[i] ) 操作,

如果返回不爲m.end(),說明有元素與A[i]匹配並相加爲k,那麼ans+1.

需要特殊注意的是m.find(A[i]) != m.end() ,說名集合中已經有一個元素值爲A[i]了

這時需要注意  k= a + a 情況,如(8 = 4 + 4)

根據上面的分析 可以很快寫出代碼來:

set<int >m;

void func(int *A, int n, int k){
    for(int i=0;i<n;i++){
        if(m.insert(A[i])== m.end()){
            if(m.find( k- A[i] )!=m.end() ){
                cout<<k-A[i]<< "  "<<A[i]<<endl;
                break;
            }else{
                m.insert(A[i]);
            }
        }else{
            if(k== A[i]+ A[i]){
                cout<<A[i]<<" "<<A[i]<<endl;
                break;
            }
        }
    }
}

當然對於這類問題的變形,如數組中存在多對數字相加得k,需要求的是存在的對數,我們可以用map一樣可以得到較高效的解。






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