题目描述
输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求时间复杂度是O(N)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
解法总结
不论原序列是有序还是无序,解决这类题有以下三种办法:
- 1、二分(若无序,先排序后二分),时间复杂度总为O(N log N),空间复杂度为O(1);
- 2、扫描一遍X-S[i] 映射到一个数组或构造hash表,时间复杂度为O(N),空间复杂度为O(N);
- 3、两个指针两端扫描(若无序,先排序后扫描),时间复杂度最后为:有序O(N),无序O(N log N + N)=O(N log N),空间复杂度都为O(1)。
所以,要想达到时间O(N),空间O(1)的目标,除非原数组是有序的(指针扫描法),不然,当数组无序的话,就只能先排序,后指针扫描法或二分(时间 O(Nlog N),空间O(1)),或映射或hash(时间O(N),空间O(N))。时间或空间,必须牺牲一个,达到平衡。
综上,若是数组有序的情况下,优先考虑两个指针两端扫描法,以达到最佳的时O(N),空O(1)效应。否则,如果要排序的话,时间复杂度最快当然是只能达到O(N log N),空间O(1)则不在话下。
默认无序,使用 hash 表的 O(n) 解法示例:
package main
import (
"fmt"
)
func TowSum(nums []int, target int) (int, int, error) {
dic := make(map[int]int)
for i, num := range nums {
t := target - num
if _, ok := dic[t]; ok {
return t, num, nil
} else {
dic[num] = i
}
}
return -1, -1, fmt.Errorf("Not Found!")
}
func main() {
nums := []int{2, 4, 6, 3}
target := 9
num1, num2, err := TowSum(nums, target)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(num1, num2)
}