一個"2-SUM"問題

來源:互聯網
上載者:User

標籤:

題目要求:

Download the text file here. (Right click and save link as).

The goal of this problem is to implement a variant of the 2-SUM algorithm (covered in the Week 6 lecture on hash table applications).

The file contains 1 million integers, both positive and negative (there might be some repetitions!).This is your array of integers, with the ith row of the file specifying the ith entry of the array.

Your task is to compute the number of target values t in the interval [-10000,10000] (inclusive) such that there are distinct numbers x,y in the input file that satisfy x+y=t. (NOTE: ensuring distinctness requires a one-line addition to the algorithm from lecture.)

Write your numeric answer (an integer between 0 and 20001) in the space provided.

OPTIONAL CHALLENGE: If this problem is too easy for you, try implementing your own hash table for it. For example, you could compare performance under the chaining and open addressing approaches to resolving collisions.

 

大致意思是說,有一百萬個數字(正負都有,且可能重複)。目標是要尋找到唯一存在的數對(x,y),使得x+y屬於[-10000, 10000]的範圍中,最後輸出這些數對的個數。

檔案中的資料差不多是這樣子的:

...-92205919974-65150999169-9624798614470191728682-59670982771-10202710755-72167080349-1922161398580341418823-79433686277873517134166084932343408017526104402824795984203784346-281203864745906443137639436465566-89458683408-64200776240-42582579303-6265688853555650079602629541755483371363921770259349593-97472959477418901481394421621297626864335558...

解題思路:

起初採用了最暴力的方法,直接把這些數字塞進一個hash table中,然後遍曆著去查詢(這個方法很不好,所以就不詳述了),結果運行了很久都沒有跑出結果,遂直接放棄這種方法。

這裡的問題在於如下兩點:

  1. 資料量多達一百萬條;
  2. 大部分數對相加的和,遠超要求的範圍之外。

因此針對問題的實際情況進行了些許最佳化,大致思路如下:

  1. 假設X為檔案中的一個數字;
  2. 建立一個hash table,它的鍵為X/10000,值為由對應X組成的set。這樣就相當於把輸入的資料以10000作為一個範圍對其進行劃分,最後劃分成若干組資料,之所以要將10000作為劃分的範圍,是因為題目中要求數對的和在[-10000, 10000]的範圍中,這樣對於我們這裡的hash table,給定一個key1,我們就能知道可能有哪些key2對應集合中的數與key1集合中的數相加,是可以在要求的範圍中的;
  3. 具體而言,對於一個key1,可取的key2有:{-key1-2, -key1-1, -key1}這三個。注意因為之前的X/10000是整除,其結果為向下取整,如 -14000 / 10000 = -2;
  4. 在已知了key1與key2之後,對其集合中的數進行迴圈遍曆,如果相加的和在題目要求的範圍內,那麼就將計數器加一。

利用上述思路,可以避免大量的不必要的運算,另外我們還可以對其進行進一步的最佳化:

  1. 對key1進行遍曆的時候,只取key1小於或等於零的值,這樣可以進一步減少重複計算;
  2. 建立一個儲存結果的set,如果找到了滿足要求的數對(x, y),那麼就置result[x+y] = True,最後輸出result的大小。

代碼實現:

有了上述的思路,利用Python對其進行了實現,代碼如下:

result = {}dic = {}input_file = open("algo1-programming_prob-2sum.txt")# 讀入資料for line in input_file:    num = long(line)    key = num/10000    if key not in dic:        dic[key] = {}    # 這裡記錄資料出現的次數,用來判斷該數是否是唯一的    if num in dic[key]:        dic[key][num] += 1    else:        dic[key][num] = 1for key1 in dic:    # 忽略key1 > 0的情況,減少不必要的重複計算    if key1 > 0:        continue    # 根據給定的key1,可以推測出key2可取的值    for key2 in range(-key1-2, -key1 + 1):        if key2 in dic:            # 對key1和key2對應集合中的數進行遍曆            for value2 in dic[key2]:                for value1 in dic[key1]:                    # 判斷這兩個數是否是唯一的                    if dic[key1][value1] != 1 or dic[key2][value2] != 1:                        continue                    sum_tmp = value1+value2                    # 判斷兩數之和是否在題目要求的範圍內                    if abs(sum_tmp) <= 10000 and sum_tmp not in result:                        result[sum] = True# 輸出結果print len(result)
input_file.close()

這段代碼在我的電腦上運行僅需要大約3-4秒的時間就能跑出結果(包含讀取資料的I/O操作的時間),可見該方法有效地避免了大量不必要的計算。

另外,題目中要求找到唯一存在的數對(x, y),但是如果把代碼中判斷唯一性的那個條件判斷去除,得到的結果也是一樣的,這也許和給出的資料有關。

一個"2-SUM"問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.