已解答go语言实现
提示
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 target
的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6 输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- 只会存在一个有效答案
方法1:最直观的就是考虑暴力遍历了,直接两个for循环嵌套,时间复杂度为n^2
package main
// 暴力解法。O(n^2)
func twoSum(nums []int, target int) []int {
slice := []int{}
for i := 0; i < len(nums); i++ {
for j := 0; j < len(nums); j++ {
if i != j {
if nums[i]+nums[j] == target {
slice = append(slice, i)
slice = append(slice, j)
return slice
}
}
}
}
return []int{}
}
需要注意的是,如果6=3+3,而nums[i]=3,nums[j]=3,则需要添加一个判断i不能与j相同,
方法2:利用记忆化,空间换取时间
package main
func twoSum2(nums []int, target int) []int {
//hashmap[value]=index,利用记忆化搜索,时间换空间
hashmap := make(map[int][]int)
//这样的话,就避免了覆盖的情况,比如数组值相同的情况,对应的键存储在一个切片里,就算问的是3数之和都行
slice := []int{0, 0}
for i := 0; i < len(nums); i++ {
hashmap[nums[i]] = append(hashmap[nums[i]], i)
if j, exists := hashmap[target-nums[i]]; exists {
for _, key := range j {
if key != i {
slice = []int{i, key}
}
}
} else {
continue
}
}
return slice
}
(伪)方3 大家不用看,在本题里是错的
其实我还考虑过,既然是两数相加等于target,为什么不直接i从1遍历到target/2呢,只要判断i和target-i是否在切片中即可,如果存在那就找到对应的索引值即可。那可以利用排序先把无序的排成有序的,再二分查找判断i是否存在。如果存在,记录下i值,二分查找target - i是否存在。如果也存在,又因为题目说了唯一性,那就可以不用再找了,再遍历原切片(未排序的状态),找到对应的索引值即可。如果二分查找完i从1到target/2的所有值,都不在切片中,那就不用遍历数组找索引了,从此可见如果target/2的值远远远小于nums[]的长度的时候,判断有没有这样一对索引存在还是有可取之处的。
但是归根到底这样是错的,因为target分成两个数,这个数可正可负,比如一个是负数,另一个可以是比target大的正数,而且target也不一定是负数。我这种方法只考虑了只有正数的情况。只适合正数。而且,写法也不简单,为了实现我的想法,操作也比较麻烦。不如方2.而且最后实际遍历的时候,也不如记忆化搜索。
func twoSum1(nums []int, target int) []int {
/* slice := make([][]int, 0)
for i := 0; i < target/2; i++ {
par := []int{i, target - i}
slice = append(slice, par)
}*/
set := make(map[int]bool)
slice := []int{}
nums1 := append([]int{}, nums...)
sort.Ints(nums1)
for i := 0; i <= target/2; i++ {
temp1 := binarySearch(nums1, i)
if temp1 != false {
temp2 := binarySearch(nums1, target-i)
if temp2 != false {
index1 := traversal(nums, i, set)
slice = append(slice, index1)
set[index1] = true
slice = append(slice, traversal(nums, target-i, set))
return slice
}
}
}
return []int{}
}
func binarySearch(num []int, target int) bool {
high := len(num) - 1
low := 0
mid := (high + low) / 2
for low <= high {
if num[mid] > target {
high = mid - 1
} else if num[mid] < target {
low = mid + 1
} else {
return true
}
mid = (high + low) / 2
}
return false
}
func traversal(nums []int, target int, set map[int]bool) int {
for i := 0; i < len(nums); i++ {
if nums[i] == target {
if set[i] == false {
return i
}
continue
}
}
return -1
}