go语言实现--找出一个数组中的两个数,这两个数之和等于一个给定的值
程序员文章站
2024-02-01 21:38:22
...
前几天面试的时候问了我一道算法题,题目是 :快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值
所以把它记录下来
解法一:穷举,从数组中任意取出两个数字,计算两者之和是否为给定的数字,时间复杂度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
推荐阅读
-
个有序的整形数组,给定一个数,在数组中找出两个数的和等于这个数,并打印其下标
-
一个整形数组,给定一个数,在数组中找出两个数的和等于这个数
-
go语言实现--找出一个数组中的两个数,这两个数之和等于一个给定的值
-
快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值
-
有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出“无此数”——C语言
-
一个数组nums,其中任意两个值等于给定值target,返回这两个值在nums里的位置
-
两数之和:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。...
-
c语言和Java语言实现,两数之和:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
-
leetcode:求两数之和,给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
-
LeetCode1.两数之和:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,返回数组下标。假设每种输入只对应一个答案。但数组中同一个元素不能使用两遍