演算法題8 在給定數列中查詢和為給定值的兩個數字

2021-05-25 09:06:15 字數 1057 閱讀 5198

題目:輸入乙個已經按公升序排序過的任意實數陣列和乙個數字,在陣列中查詢兩個數,使得它們的和正好是輸入的那個數字。要求時間複雜度是o(n)。如果有多對數字的和等於輸入的數字,輸出任意一對即可。

例如輸入陣列1、2、4、7、11、15和數字15。由於4+11=15,因此輸出4和11。

分析:如果我們不考慮時間複雜度,最簡單想法的莫過去先在陣列中固定乙個數字,再依次判斷陣列中剩下的n-1個數字與它的和是不是等於輸入的數字。可惜這種思路需要的時間複雜度是o(n2)。

解題思路1:組建這個陣列的hash表,或者利用stl裡的multiset結構,此時不需要輸入陣列是否已排序。對每個元素a,查詢hash表中是否存在p-a。這種思路時間複雜度是o(n),空間複雜度是o(n),利用了空間複雜度來換取時間複雜度。

解題思路2:利用已有的陣列已排序這個條件。

我們假設現在隨便在陣列中找到兩個數。如果它們的和等於輸入的數字,那太 好了,我們找到了要找的兩個數字;如果小於輸入的數字呢?我們希望兩個數字的和再大一點。由於陣列已經排好序了,我們是不是可以把較小的數字的往後面移動 乙個數字?因為排在後面的數字要大一些,那麼兩個數字的和也要大一些,就有可能等於輸入的數字了;同樣,當兩個數字的和大於輸入的數字的時候,我們把較大 的數字往前移動,因為排在陣列前面的數字要小一些,它們的和就有可能等於輸入的數字了。

我們把前面的思路整理一下:最初我們找到陣列的第乙個數字和最後乙個數字。當兩個數字的和大於輸入的數字時,把較大的數字往前移動;當兩個數字的和小於數字時,把較小的數字往後移動;當相等時,打完收工。這樣掃瞄的順序是從陣列的兩端向陣列的中間掃瞄。

問題是這樣的思路是不是正確的呢?這需要嚴格的數學證明。感興趣的讀者可以自行證明一下。

參考**:

ps:也可使游標從中間向兩邊滑動。

擴充套件:如果給定乙個整數數列,數列中任意乙個數字不重複,且取值可能為1~n(n為乙個較大的數)。找出數列中符合條件的數對個數,滿足數對中兩數和等於n+1,複雜度是o(n).

解題思路1,如果不考慮空間複雜度,可以使用上題解題思路1的方法(由於此題為正整數且無重複,遍歷一半即可)。時間複雜度為o(n/2),空間複雜度為o(n).

解題思路2:應該還有更加優化的演算法。

在排序陣列中查詢和為給定值的兩個數字

14 題目 輸入乙個已經按公升序排序過的陣列和乙個數字,在陣列中查詢兩個數,使得它們的和正好是輸入的那個數字。要求時間複雜度是o n 如果有多對數字的和等於輸入的數字,輸出任意一對即可。例如輸入陣列1 2 4 7 11 15和數字15。由於4 11 15,因此輸出4和11。思路 由於陣列為公升序,因...

14 在排序陣列中查詢和為給定值的兩個數字

題目 輸入乙個已經按公升序排序過的陣列和乙個數字,在陣列中查詢兩個數,使得它們的和正好是輸入的那個數字。要求時間複雜度是o n 如果有多對數字的和等於輸入的數字,輸出任意一對即可。例如輸入陣列1 2 4 7 11 15和數字15。由於4 11 15,因此輸出4和11。分析 如果我們不考慮時間複雜度,...

100題 在排序陣列中查詢和為給定值的兩個數

在排序陣列中查詢和為給定值的兩個數 include using namespace std bool findnum int data,unsigned int length,int sum,int n1,int n2 int ahead length 1 int behind 0 while ah...