LeetCode 1.两数之和

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;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值