1 从头开始——leetcode_001简介
果然古人诚不欺我,万事开头难,还打着简单的标签🐶。leetcode第一题"两数之和”,不知道劝退了多少人。
题目描述
示例
2 解法
2.1 解法一
最为简单直接的思路,就是把输入数组nums里的元素两两相加一遍,看是否等于target,如果等于就返回对应的两个元素的数组下标。
这种方法需用到两个循环,时间复杂度
O
(
n
2
)
O(n^2)
O(n2)。在代码实现上比较简单:
func twoSum(nums []int, target int) []int {
for k,_ := range nums{
for i := k + 1; i < len(nums); i++{
if nums[k] +nums[i] == target{
return []int{k,i}
}
}
}
return nil
}
在实际测试中,很容易就超时。上面使用go的测试结果虽然可以通过,但是执行时间不是很理想。
所以,需要对它稍加改进。
解法二
在解法一的基础上,如果可以在某一次循环中将获得的结果保留下来,采用哈希表(或树形结构)存储,那么再查找时只需根据索引查找,时间复杂度则为 O ( 1 ) O(1) O(1),整体的复杂度则为 O ( n ) O(n) O(n),比解法一强不少。
具体思路:
- 首先生成一个空的哈希表,record
- 遍历nums中元素,假设当前遍历到元素为e。在遍历到每一个元素时,查找哈希表record中是否有key与元素e的和等于target。
- 如果有,则返回e的下标和哈希表该key所对应的value;如果没有,则将元素e作为key,元素e对应的下标作为value存入record中。
- 一直循环直至遍历nums中所有元素,没有符合条件则返回空。
在各种语言中都有相应的数据结构(如python中的dictionary、java中的map)可用于实现。采用go的实现如下:
func twoSum(nums []int, target int) []int {
record := make(map[int]int)
for k,v := range nums{
if _, ok := record[target - v];ok{
return []int{k, record[target - v]}
}
record[v] = k
}
return nil
}
这次的执行结果比较好,时间复杂度成功超过了96.99%。
动画演示
(上图中的record采用树形结构展示,只是一个示例,真实的实现未必是如此)
欢迎关注