【Leetcode01】两数之和(Python实现)

给定一个整数数组 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
只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?


一、个人思路

例如对一个长度为4的数组,遍历数组的(i, j)对按照如下顺序对数组进行遍历。一旦发现nums[i]+nums[j]==target,立即return。从而保证只存在一个有效答案。

[0,3]
[0,2]
[0,1]
[1,3]
[1,2]
[2,3]

1.1 Python

1.1.1 语法知识点

  1. 函数语法
    range(start, stop[, step])

参数说明:
start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5);
stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
step: 步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1);步长为负数时可以从后往前遍历,例如:range(10, 0 , -1)是[10,9,8,7,6,5,4,3,2,1],末尾不包括0

  1. 列表(List)

append() 方法用于在列表末尾添加新的对象。
在这里插入图片描述
3. Python enumerate() 函数

  • 描述:
    enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。Python 2.3. 以上版本可用,2.6 添加 start 参数。

  • 语法
    以下是 enumerate() 方法的语法:
    enumerate(sequence, [start=0])

  • 参数

    • sequence – 一个序列、迭代器或其他支持迭代对象。
    • start – 下标起始位置的值。例如,令start=1,则该对象的下标从1开始。
  • 返回值

    • 返回 enumerate(枚举) 对象。

使用enumerate()和字典dictionary相结合,可以在python中实现Hash表

python中in在set和dict中的使用

Python字典(dict )的几种遍历方式

1.1.2 实现代码

  • leetcode上python提交
class Solution(object):
    def twoSum(self, nums, target): 
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """

        """
        # 外层循环指针i从数组头开始遍历
        # 内层指针j从数组尾开始遍历,j的值不能小于或等于i,即要保证j一直在i后面
        """

        list_ans=[]
        # 不包含nums[len(nums)-1]是因为j指向这个位置,为了避免生成重复数据
        for i in range(0,len(nums)-1):
            for j in range(len(nums)-1,i,-1):
                if (nums[i]+nums[j]==target):
                    list_ans.append(i)
                    list_ans.append(j)
                    return list_ans

  • leetcode上python3提交
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        list_ans=[]
        # 不包含nums[len(nums)-1]是因为j指向这个位置,为了避免生成重复数据
        for i in range(0,len(nums)-1):
            for j in range(len(nums)-1,i,-1):
                if (nums[i]+nums[j]==target):
                    list_ans.append(i)
                    list_ans.append(j)                    
                    # 可以不用append()将数据添加到list里再返回
                    # 可以直接 return [i,j]                 
                    return list_ans
                    
        # return [] 加了这句又要多额外的内存消耗,不加了

补充: Python3提交时,给的模板函数头上的诸如-> List[int]等我之前没见过的语句令我非常疑惑,后来查阅得知:

模板里使用了类型标注,具体是 python 标准库 typing 里的 List[1]。

nums: List[int] 标注了 nums 应该是 list,且这个 list 中的元素均为 int。

使用类型标注能增加一些类型检查,更早报告代码问题。
参考
^https://docs.python.org/3/library/typing.html#typing.List

二、 题解

https://leetcode.cn/problems/two-sum/solution/zhu-jian-you-hua-yi-zhi-dao-zui-you-pei-sexli/
官方题解

2.1 暴力解法-线性查找

我的解法和这个类似,虽然我的j是从后往前遍历的,也不是采取比较值的方法,但本质上还是一个时间复杂度为 O ( n 2 ) O(n^2) O(n2)的算法。

2.2 二分查找优化线性查找

线性查找时间复杂度为 O ( n ) O(n) O(n)
二分查找时间复杂度为 O ( l o g n ) O(logn) O(logn)

注: 二分查找的使用前提是,该区间内的数据是有序的。
所以要先对数组进行排序,但是排序后会导致数组每个元素的索引和原来的数字不一样。
在python中,可以把数组构造成字典(Dictionary)键值对,原索引放在key值中。
此时,时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),空间复杂度为 O ( n ) O(n) O(n)所以此种方法也不是优解。

2.3 哈希查找优化

线性查找时间复杂度为 O ( n ) O(n) O(n)
二分查找时间复杂度为 O ( l o g n ) O(logn) O(logn)
(未发生任何hash碰撞)哈希查找时间复杂度为 O ( 1 ) O(1) O(1)

此时,算法的时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)

2.3.1 思路及算法

使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O ( n ) O(n) O(n)降低到 O ( 1 ) O(1) O(1)

这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。

2.3.2 评论区精选

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.3.3 Python代码

  • 用enumerate()
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashtable = dict()
        for i, num in enumerate(nums):  # 遍历nums列表的下标i和数值num
            if target - num in hashtable: # in遍历的是dict中的key值target - num, target - num
                return [hashtable[target - num], i]
            hashtable[nums[i]] = i # (写完for,思考的时候先写这行)key值存放nums[i],value值存放i
        return []
  • 不用enumerate()

def twoSum(self, nums: List[int], target: int) -> List[int]:
    num_index_map = dict()

    for i in range(len(nums)):
        x = nums[i]
        if (target - x) in num_index_map:
            index = num_index_map[target - x]
            # 返回的[index,i]应该前一个数小,后一个数大
            # 已经存在num_index_map中的index,肯定比才从nums中读入的下标i要小,所以顺序的index在先。
            return [index, i]
        num_index_map[x] = i
                
    return []
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值