1. 程式人生 > >go語言實現--找出一個數組中的兩個數,這兩個數之和等於一個給定的值

go語言實現--找出一個數組中的兩個數,這兩個數之和等於一個給定的值

前幾天面試的時候問了我一道演算法題,題目是 :快速找出一個數組中的兩個數字,讓這兩個數字之和等於一個給定的值

所以把它記錄下來

解法一:窮舉,從陣列中任意取出兩個數字,計算兩者之和是否為給定的數字,時間複雜度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