两数之和25101

1. 两数之和

已解答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
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值