0. 原理
具体可以参考我的另一篇文章。
1. 两数之和(leetcode_1)
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums = [2, 7, 11, 15], target = 9> 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
此题有三种解法:
- 暴力法
 时间复杂度
;空间复杂度
- 两遍哈希表法
 时间复杂度
;空间复杂度
- 一遍哈希表法
 时间复杂度
;空间复杂度
1.1 暴力解法
时间复杂度;空间复杂度
class Solution(object):def twoSum(self, nums, target):""":type nums: List[int]:type target: int:rtype: List[int]"""length = len(nums)for first_index in range(length-1):for second_index in range(first_index+1, length):if nums[first_index] + nums[second_index] == target:return [first_index, second_index]else:return -1
1.2 两遍哈希表
即空间换时间的思想。时间复杂度;空间复杂度
。
class Solution(object):def twoSum(self, nums, target):""":type nums: List[int]:type target: int:rtype: List[int]"""dict_ = {}for index, val in enumerate(nums):dict_[val] = indexfor index, val in enumerate(nums):if target - val in dict_.keys():if index != dict_[target-val]:return [index, dict_[target-val]]return -1
1.3 一遍哈希表法
即有点类似于动态规划搜索,一边遍历一边存储一边查找的思想。时间复杂度;空间复杂度
。
class Solution(object):def twoSum(self, nums, target):""":type nums: List[int]:type target: int:rtype: List[int]"""dict_ = {}for index, val in enumerate(nums):if target - val in dict_.keys():return [index, dict[target-val]]else:dict_[val] = indexreturn -1
这里需要注意两点:
- 哈希表的hashMap.containsKey()平均复杂度为
 ,最坏状况为
,实际中看做
即可。
- 虽然一遍哈希和两遍哈希时间和空间复杂度表面上一样,但是实际运行中,一遍哈希还是比两遍哈希更快的,因为实际情况中需要完全遍历到列表末尾的概率很小,但是他们的整体复杂度是相同的,这一知识点具体可以参考我的另一篇关于复杂度
 的文章。
- 暴力法和哈希法各有各的优劣,并没有绝对的好与坏之分,应该具体情况具体分析。比如
 
- 当我们空间足够大需要时间尽可能短,即算法相应尽可能快的话,当然哈希法更好;
 - 当列表中的数字非常多,我们的空间内存不足,并且并不太在意时耗时,当然暴力法更好。
 
