1.题目描述
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2.思路
2.1 暴力求解
两个for循环嵌套,第一层循环改变第一个整数,第二层循环寻找与第一个整数的和为target的那个整数,找到之后返回下标。要注意的是第二层循环中需要判断两个整数的数组下标是否相同。
代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
maxIndex = len(nums)
for i in range(maxIndex):
for j in range(maxIndex):
if (nums[j] == target - nums[i]) and (i != j):
return [i, j]
接下来是对暴力破解的一些优化
优化1:
不需要第二层循环,采用 in 判断整数是否在数组中,如果在,就用 list.index() 来获取下标。
代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
maxIndex = len(nums)
for i in range(maxIndex):
if((target - nums[i]) in nums):
j = nums.index(target - nums[i])
if j != i :
return [i, j ]
优化2:
用 in 进行判断时,不需要对整个数组进行判断,而只需要对列表中第一层循环中那个整数之前的数字(之后的也可以)进行判断即可。
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
maxIndex = len(nums)
for i in range(maxIndex):
if((target - nums[i]) in nums[:i]):
j = nums[:i].index(target - nums[i])
return [i, j]
2.2 采用字典进行映射
利用字典来先将 nums 列表中的整数值与其index进行映射,然后在字典中查找数值。
字典中的键值对表示为 key:value 。
字典值可以是任何的 python 对象,既可以是标准的对象,也可以是用户定义的,但键不行。
两个重要的点需要记住:
1)不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住
2)键必须不可变,所以可以用数字,字符串或元组充当,而用列表就不行
本题中将 nums 中的整数值做为 key, 而将整数的 index 做为 value。nums中如果有重复出现的整数,按此方法得到的第二个整数会取其在 nums 中较大的 index 。
代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dict = {}
for index, value in enumerate(nums):
dict[value] = index
for index, value in enumerate(nums):
j = dict.get(target - value)
if j is not None and j != index:
return [index, j]
优化1:
注意到这里有两个同样的 for 循环,因此考虑进行合并。再想到 2.1 节优化2 中提到的,只需要对之前的部分进行查找,因此可做合并,代码如下:
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dict = {}
for index, value in enumerate(nums):
j = dict.get(target - value)
if j is not None and j != index:
return [index, j]
dict[value] = index
注意这里需要先对第二个整数是否存在进行判断,然后再向字典中插入新的键值对。
本来认为这样可以在后续的查找上降低时间,但是发现实际效果和没有优化的差不多。分析应该是因为字典中的查找时间复杂度是O(1),所以减少字典中键值对个数不能提高查找速度,因此基本上是没有优化。这里也加深了我对于字典查找的理解。
下面再附上java代码:
import java.util.*;
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[] {};
Map<Integer, Integer> map = new HashMap<>();
int index = 0;
for(int i : nums) {
if(map.containsKey(target - i)) {
result = new int[] {map.get(target - i), index};
break;
}
map.put(i, index);
index ++;
}
return result;
}
}