定一個整型數組(數組中的元素可重復,已排序),以及一個指定的值。找出數組中兩數之和為指定值的所有整數對,要求時間復雜度為O(N)。
首先來分析一下這個題,假設題目沒有說已排序和時間復雜度的要求,那么用最暴力的方法就是直接遍歷兩次數組,時間復雜度為O(N*N)。這里也來實現一下,代碼如下:
/*暴力法,直接遍歷兩次數組,時間復雜度為O(n*n) */ function getSum (arr, sum) { if (arr == '' || arr.length == 0) { return false; } for (var i = 0; i < arr.length; i++) { for (var j = i + 1; j < arr.length; j++) { if (arr[i] + arr[j] == sum) { console.log(arr[i] + ' + ' + arr[j] + ' = ' + sum); } } } }
如果題目沒有寫明已排序,那么可以先將整型數組排序,排序之后定義兩個指針left和right。left指向已排序數組中的第一個元素,right指向已排序數組中的最后一個元素,將 arr[left]+arr[right]與 給定的元素比較,若前者大,right--;若前者小,left++;若相等,則找到了一對整數之和為指定值的元素。此方法采用了排序,排序的時間復雜度為O(NlogN),排序之后掃描整個數組求和比較的時間復雜度為O(N)。故總的時間復雜度為O(NlogN),空間復雜度為O(1)。
那么現在題目中已經寫明已排序,所以就可以直接用上面的思路進行實現,那么時間復雜度就是O(N)。接下來附上我的代碼實現:
function getSum (arr, sum) { if (arr == '' || arr.length == 0) { return false; } var left = 0; var right = arr.length - 1; while (left < right) { if (arr[left] + arr[right] > sum) { right--; } else if (arr[left] + arr[right] < sum) { left++; } else { console.log(arr[left] + ' + ' + arr[right] + ' = ' + sum); left++; right--; } } }
思路:
第一個思路,遍歷數組中的某一個數,對於每個數再一次遍歷數組中的所有數,找到滿足條件的兩個數。這個算法的時間復雜度為O(n2),空間復雜度為O(1)。
第二個思路,在前一個算法的基礎上降低時間復雜度。我們可以將數組排序,然后定義兩個指針,一個指針從左向右,另一個從右向左,遍歷直到找到滿足條件的兩個數。
由於排序的最佳時間復雜度為O(nlogn),兩個指針的遍歷時間復雜度為O(n)。所以總的時間復雜度為O(nlogn)
第三個思路,我希望通過O(n)的時間復雜度完成要求。第一遍O(n)的算法將每個數據a對應的target-a建立查詢的數據結構,例如Hash表;第二遍遍歷時,查詢每個數
是否在Hash表中,每次查詢時間復雜度為O(1),總的時間復雜度是O(n)。但是Hash表將需要一定的存儲空間,為了節省空間,我們可以采用bitmap的方法來最大化的壓
縮空間復雜度。
第二個思路,在前一個算法的基礎上降低時間復雜度。我們可以將數組排序,然后定義兩個指針,一個指針從左向右,另一個從右向左,遍歷直到找到滿足條件的兩個數。
由於排序的最佳時間復雜度為O(nlogn),兩個指針的遍歷時間復雜度為O(n)。所以總的時間復雜度為O(nlogn)
第三個思路,我希望通過O(n)的時間復雜度完成要求。第一遍O(n)的算法將每個數據a對應的target-a建立查詢的數據結構,例如Hash表;第二遍遍歷時,查詢每個數
是否在Hash表中,每次查詢時間復雜度為O(1),總的時間復雜度是O(n)。但是Hash表將需要一定的存儲空間,為了節省空間,我們可以采用bitmap的方法來最大化的壓
縮空間復雜度。
原文:https://blog.csdn.net/u010297791/article/details/70242559