go語言實現--找出一個數組中的兩個數,這兩個數之和等於一個給定的值
阿新 • • 發佈:2019-01-04
前幾天面試的時候問了我一道演算法題,題目是 :快速找出一個數組中的兩個數字,讓這兩個數字之和等於一個給定的值
所以把它記錄下來
解法一:窮舉,從陣列中任意取出兩個數字,計算兩者之和是否為給定的數字,時間複雜度O(N^2)
解法二:hash表。因為給定一個數字,根據hash表對映查詢另一個數字是否在陣列中,只需要O(1)時間。這樣的話,總體的演算法複雜度可以降低到O(N),但這種方法需要額外增加O(N)的hash表儲存空間。
解法三: 排序後對陣列中的每個數字arr[i]都判別 Sum-arr[i] 是否在陣列中,這樣,就變成一個二分查詢的演算法了。時間複雜度O(N* log2N)
程式碼如下:
package main import ( "fmt" "sort" ) func main() { arr := []int{-5, 8, 7, 3, 1, 0, 2, -1, 4} point, ok := SumSearch(arr, 3) fmt.Println(point, ok) result := SumSearch2(arr, 3) fmt.Println(result) //返回值 type Point struct { a, b int } //找出陣列中的兩個數,讓這兩個數之和等於一個給定的值 //找到第一對數即返回 func SumSearch(arr []int, sum int) (Point, bool) { length := len(arr) sort.Ints(arr) for i := 0; i < length-1; i++ { j := BinSearch(arr, i+1, length-1, sum-arr[i]) if j != -1 { return Point{arr[i], arr[j]}, true } } return Point{}, false } //找出所有符合的數放到是slice裡面一起返回出去 func SumSearch2(arr []int, sum int) []Point { var result []Point length := len(arr) sort.Ints(arr) for i := 0; i < length-1; i++ { j := BinSearch(arr, i+1, length-1, sum-arr[i]) if j != -1 { result = append(result, Point{arr[i], arr[j]}) } } return result } //二分查詢 func BinSearch(arr []int, low, high, k int) int { if low < 0 || high < 0 { return -1 } for low <= high { mid := low + (high-low)>>1 if k < arr[mid] { high = mid - 1 } else if k > arr[mid] { low = mid + 1 } else { return mid } } return -1 }
結果如下:
解法四:
還可以換個角度來考慮問題,假設已經有了這個陣列的任意兩個元素之和的有序陣列(長為N^2)。那麼利用二分查詢法,只需用O(2*log2N)就可以解決這個問題。當然不太可能去計算這個有序陣列,因為它需要O(N^2)的時間。但這個思考仍啟發我們,可以直接對兩個數字的和進行一個有序的遍歷,從而降低演算法的時間複雜度。
首先對陣列進行排序,時間複雜度為(N*log2N)。
然後令i = 0,j = n-1,看arr[i] + arr[j] 是否等於Sum,如果是,則結束。如果小於Sum,則i = i + 1;如果大於Sum,則 j = j – 1。這樣只需要在排好序的陣列上遍歷一次,就可以得到最後的結果,時間複雜度為O(N)。兩步加起來總的時間複雜度O(N*log2N),下面這個程式就利用了這個思想,程式碼如下所示:
package main import ( "fmt" "sort" ) func main() { arr := []int{-5, 8, 7, 3, 1, 0, 2, -1, 4} point, ok := SumSearch(arr, 3) fmt.Println(point, ok) } //返回值 type Point struct { a, b int } func SumSearch(arr []int, sum int) (Point, bool) { length := len(arr) sort.Ints(arr) for i, j := 0, length-1; i < j; { if arr[i]+arr[j] == sum { return Point{arr[i], arr[j]}, true } else if arr[i]+arr[j] < sum { i++ } else { j-- } } return Point{}, false }
結果如下:
參考文章:https://blog.csdn.net/mimi9919/article/details/51335337