LeetCode---1 两数之和

     第一次接触到leetcode的题目,和一位姑娘“饶有兴趣”的聊到了深夜。当时的第一想法就是循环遍历,暴力破解,耿直的很。之后她和我说的哈希表解法也没太明白。

     直到昨天,有两个题目,一个三位数,一个四位数。他们说,唉,...有一个说我在力扣解题解不出来,老师你能不能教我暴力解法,诶...帮助治疗一下,我的脱发.

     我说可以,你在力扣上挠头死磕练死劲,不好用,他不服气。

     诶...我说小朋友,你用三个for循环来解这个题,他解不动。

     他说你这也没用。我说我这个有用,这是冲劲儿,传统功夫是讲冲劲儿的,一力降十会。

     五位数的力扣秃头怪,都难不住我这一个for循环啊…哈!

     他非要和我试试,我说可以。诶…我一说完他啪就站起来了,很快啊!........


     哈哈,看到了四数之和的时候,也用的暴力解法,然后超时了........这时候才知道认真看别人的解法,看到的双指针,递归解法很有启发,重新回看两数之和,将想法梳理一遍。

题目 

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum

解法

1.暴力解法

两个for循环,直接KO!

class Solution():
    def answer(self,nums,target):
        for i in range(len(nums)) :
            for j in range(len(nums)):
                if nums[i] + nums[j] == target and i != j:
                    return [i,j]
#run time: 36ms  memory consump: 14.9MB 

感觉运行时间不太靠谱,提交了两次,一次48ms,一次36ms.平方阶的时间复杂度。

2.指针

看到四数之和的双指针,有考虑两数之和能不能应用同样的方法。

然而指针的移动需要基于数组是有序的,这样指针才能确定移动方向,两数之和返回的是数组下标,如果排序的话,需要重新找回原来的数组下标。

先尝试写一个指针从右往ZUO寻找的:

class Solution():
    def answer(self,nums,target):
        for i in range(len(nums)-1) :
            q = len(nums) - 1 
            while q > i :
                if nums[q] + nums[i] == target :
                    return [i,q]
                else :
                    q -= 1
#run time: 44ms  memory consump: 15MB 

 平方阶的时间复杂度

尝试两个指针,此时需要对数组进行排序:

class Solution():
    def answer(self,nums,target):
        numsCopy = nums.copy()
        nums.sort()
        result = []
        p = 0
        q = len(nums)-1
        while q > p :
            if nums[p] + nums[q] == target :
                break
            elif nums[p] + nums[q] > target :
                q -= 1
            else :
                p += 1  
        #ZUO 和 右 的指针都可以动 
        for i in range(len(numsCopy)):
            if numsCopy[i] == nums[p] or numsCopy[i] == nums[q]:
                result = result + [i]
        #找到初始的索引值
        return result
#run time: 48ms  memory consump: 14.8MB 

 线性的时间复杂度

3.哈希表

简单说,就是从列表依次取一个值,被目标值减去,得出的结果在已有的哈希表中查找,如果有,那么返回该值的索引和哈希表中相同值的索引号,如果没有,把这个值放入哈希表中,继续重复。

class Solution:
    def answer(self, nums, target):
        hashtable = dict()
        for index, num in enumerate(nums):
            if (target - num) in hashtable:
                return [hashtable[target - num], index]
            hashtable[nums[index]] = index
        return []
#run time: 24ms  memory consump: 14.7MB 

效率提高明显.

4.递归

class Solution():
    def twoSum(self,nums,target):
        result = []
        def find(i,target,solution):
            if target == 0  and len(solution) == 2 :
                result.append(solution[0])
                result.append(solution[1])
                return  
            elif len(solution) > 2 or i >= len(nums):
                return
            find(i+1,target,solution)
            find(i+1,target-nums[i],solution+[i])
        find(0,target,[])
        return result
#21/52 over time ...

因为这个题目要求返回数组下标,后面的三数之和或者四数之和返回的是数值,可以将其进行排序,然后在递归的时候会进行判断,对于不可能存在结果的分支就直接pass了,而这个就是全部分支都要进行下去,所以可能是这个原因导致超时了。如果对数组进行排序之后,就会好很多,但是需要找回排序之前的索引号。正好题目中有这个假设:每种输入只会对应一个答案,所以:

class Solution():
    def twoSum(self,nums,target):
        numsCopy = nums.copy()
        nums.sort()
        result = []
        def find(i,target,solution):
            if target == 0  and len(solution) == 2 :
                result.append(solution[0])
                result.append(solution[1])
                return  
            elif len(solution) > 2 or i >= len(nums):
                return
            if target - nums[i]-nums[-1] > 0 :  
                find(i+1,target,solution)
            elif target-(2-len(solution))*nums[i] < 0 :
                return
            #没有希望的分支就不在继续递归了
            find(i+1,target,solution)
            find(i+1,target-nums[i],solution+[nums[i]])
        find(0,target,[])
        resultNosort = []
        for i in range(len(numsCopy)):
            if numsCopy[i] == result[0] or numsCopy[i] == result[1] :
                resultNosort = resultNosort + [i]
         #找到未排序之前的索引号
        return resultNosort
#20/52  over time....

所以这么写貌似没有什么太大帮助!!!!

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值