Leetcode | 两数之和笔记

1、两数之和

题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标

题目分析与实现

难度:【简单】

数据结构:数组

基本实现方法:

  • 暴力枚举法
  • 双指针法
  • 哈希表法等
实现一:暴力枚举
  • 枚举数组中的每一个数 x,寻找数组中是否存在 target - x
  • 每一个元素不能被使用两次,所以只需要在 x 后面的元素中寻找 target - x
# Use Python to solve
def two_sum(nums: List[int], target:int) -> List[int]:
    '''
    使用暴力枚举法求两数之和
    
    参数:
        nums (list[int]): 包含整数的列表
        target(int): 目标和
    
	返回值:
    	list[int]: 包含两个索引的列表,这两个索引对应的元素之和等于目标和target如果没有找到符合条件的索引对,返回空列表[]

    '''
    arr_length = len(nums)    
    if not nums or arr_length < 2:
        return []
       
    # 使用暴力枚举法来一一确认符合条件的元素索引
    for i in range(arr_length):
        for j in range(i + 1, arr_length):
            if nums[i] = target - nums[j]
            	return [i, j]
            
    

时间复杂度分析:

  • 最好情况:如果在第一次遍历中就找到了符合条件的索引对,则时间复杂度为 O ( 1 ) O(1) O(1)
  • 最坏情况:如果没有找到符合条件的索引对,需要完整地遍历两层循环,时间复杂度为 O ( n 2 ) O(n^2) O(n2),其中n是nums列表的长度
  • 平均情况:平均情况下,需要遍历两层循环,时间复杂度为 O ( n 2 ) O(n^2) O(n2)

空间复杂度分析:

  • 没有使用额外的空间,只使用了常数级别的变量存储数据,所以空间复杂度: O ( 1 ) O(1) O(1)
实现二:双指针法
  • 创建一个列表(List)按元组方式存放数组的值和索引,并对其进行排序(按值)
  • 定义左右指针,当左指针小于右指针时,进行循环判断
  • 如果左右指针值的和等于目标值,则将其索引添加到一个新列表当中(num_list)
# Use Python to solve 
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        '''
        使用双指针方法解决两数之和

        参数:
            nums (list[int]): 整数数组
            target(int): 目标值            

        返回值:
            nums_list(list[int]): 和为目标值的两个整数的数组下标
        '''
        arr_length = len(nums)
        if not nums or arr_length < 2:
        	return []
        
        # 存放最终结果
        num_list = []  

        # 创建一个列表按(num, index)格式存放
        nums_with_index = [(num, index) for index, num in enumerate(nums)]
        # 对nums_with_index按照数字大小进行排序
        nums_with_index.sort()
        
        
        # 定义左右两个指针
        left, right = 0, arr_length - 1
        
        # 当左指针小于右指针时,进行循环
        while left < right:
            # 如果左指针和右指针所指数字的和等于目标值
            if nums_with_index[left][0] + nums_with_index[right][0] == target:               
                num_list.append(nums_with_index[left][1])
                num_list.append(nums_with_index[right][1])
                break
            # 如果左指针和右指针所指数字的和小于目标值
            elif nums_with_index[left][0] + nums_with_index[right][0] < target:
                # 左指针右移
                left += 1            
            else:
                # 右指针左移
                right -= 1
        
        return num_list

时间复杂度分析:

  • 最好情况:如果在第一次循环中就找到了符合条件的数字对,时间复杂度为 O ( 1 ) O(1) O(1)
  • 最坏情况:如果没有找到符合条件的数字对,需要遍历整个列表,时间复杂度为 O ( n ) O(n) O(n),其中n是列表nums_with_index的长度
  • 平均情况:平均情况下,需要遍历整个列表,时间复杂度为 O ( n ) O(n) O(n)

空间复杂度分析:

  • 创建了额外空间:nums_with_index,所以空间复杂度均为 O ( n ) O(n) O(n)
实现三:哈希表
  • 为数组创建一个哈希表
  • 对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配
# Use Python to solve 
def two_sum(nums: List[int], target: int) -> List[int]:
    '''
    使用哈希表方法解决两数之和问题
    
    参数:
        nums (list[int]): 包含整数的列表
        target (int): 目标和值
        
    返回值:
        List[int]: 包含两个索引的列表,这两个索引对应的元素之和等于目标和target如果没有找到符合条件的索引对,返回空列表[]
    '''
    arr_length = len(nums)
    if not nums or arr_length < 2:
        return []
    
    nums_map = {}  # 创建一个空的哈希表,用于存储数字和索引的映射关系
    
    for i, num in enumerate(nums):  # 遍历列表,同时获取数字的索引
        if target - num in nums_map:  # 如果target - num在哈希表中存在,说明之前出现过一个数字与当前num之和等于target
            return [nums_map[target - num], i]  # 返回之前记录的索引和当前索引
        nums_map[num] = i  # 将当前数字和索引添加到哈希表中
    
    return []  # 如果没有找到符合条件的索引对,返回空列表[]

时间复杂度分析:

  • 最好情况:如果在遍历列表时的第一个元素就找到了符合条件的数字对,时间复杂度为 O ( 1 ) O(1) O(1)
  • 最坏情况:如果没有找到符合条件的数字对,需要完整地遍历整个列表,时间复杂度为 O ( n ) O(n) O(n),其中n是列表nums的长度
  • 平均情况:平均情况下,需要遍历整个列表,时间复杂度为 O ( n ) O(n) O(n)

空间复杂度分析:

  • O ( n ) O(n) O(n)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是希望

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值