【leetcode】1. 两数之和——寻找两数和为目标值得组合

题目描述

给定一个整数数组 n u m s nums nums 和一个目标值 t a r g e t target target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

输出示例:

给定 n u m s = [ 2 , 7 , 11 , 15 ] , t a r g e t = 9 nums = [2, 7, 11, 15], target = 9 nums=[2,7,11,15],target=9
因为 n u m s [ 0 ] + n u m s [ 1 ] = 2 + 7 = 9 nums[0] + nums[1] = 2 + 7 = 9 nums[0]+nums[1]=2+7=9
所以返回 [ 0 , 1 ] [0, 1] [0,1]

思路1

非常自然能够想到的一种思路是:两个嵌套的 f o r for for循环。

  1. 第一个循环从 0 0 0开始遍历 n u m s nums nums,记每次得到 n u m s [ i ] nums[i] nums[i]
  2. 内嵌的第二个 f o r for for循环从 i + 1 i+1 i+1开始遍历 n u m s nums nums,记每次得到 n u m s [ j ] nums[j] nums[j]
  3. 每一步判断 n u m s [ i ] + n u m s [ j ] nums[i]+nums[j] nums[i]+nums[j]是否等于 t a r g e t target target,等于则直接返回。

这种思路实现简单,但时间复杂度稍高为 o ( n 2 ) o(n^2) o(n2)

代码

def twoSum(nums, target):
        for i in range(len(nums)):
            for j in range(i + 1, len(nums)):
                sum = nums[i] + nums[j]
                if sum == target:
                    return [i, j]
        return []

思路2——逼夹法

假如数组为有序的情况,分别将指针 i i i j j j指向数组首位,那么我们可以通过当前和 t m p S u m = n u m s [ i ] + n u m s [ j ] tmpSum=nums[i]+nums[j] tmpSum=nums[i]+nums[j] t a r g e t target target的关系进行有目的地移动 i i i j j j:小于目标值, i i i自增;大于目标值 j j j自减。这便是逼夹法。
由于nums并不是有序的,那么需要先对数组进行一次 o ( n log ⁡ ( n ) ) o(n\log(n)) o(nlog(n))的排序,再利用逼夹法,显而易见逼夹法的时间复杂度为 o ( n ) o(n) o(n),所以整体复杂度也就是 o ( n log ⁡ ( n ) + n ) o(n\log(n)+n) o(nlog(n)+n)

*注意:原题需要返回原数组下标,实际上只用逼夹是不合适的,因为得到的下标是排序后的数组下标,但该方法是能够获得相应的数值组合的。

代码

def twoSum(self, nums, target):
    nums.sort()  # 从小到大排序
    i = 0  # 头指针
    j = len(nums) - 1  # 尾指针
    result = []
    while True:  # 一直循环直至i>=j
        sum = nums[i] + nums[j]
        if sum == target:  # 假如和便是目标
            result.append([i, j])  # 记录结果
            # 确定下一轮的指针
            ii = i + 1
            while ii < j and nums[ii] == nums[i] :  # 跳掉重复的
                ii += 1
            i = ii
            jj = j - 1
            while jj > i and nums[jj] == nums[j]:  # 跳掉重复的
                jj -= 1
            j = jj
        elif sum > target:  # 假如过大,j向前移动,即减少和
            j -= 1
        else:  # 假如过小,i向后移动,即增加和
            i += 1
        if i >= j:  # 逼夹跳出条件
            break
    return result

参考

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值