双指针法与哈希查表法


两数之和

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

> 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

> 示例:

> 给定 nums = [2, 7, 11, 15], target = 9

> 因为 nums[0] + nums[1] = 2 + 7 = 9
> 所以返回 [0, 1]


思路:



1、使用暴力搜索法,两层循环。



2、采用hash表,用空间换时间,减少循环次数,遍历a,得到匹配表[b=target-a],与a匹配。

举例:

hash=[],target=7,a=2,假设列表中存在5,那么就说存在一个匹配,但是此时列表中为空,找不到与之匹配的元素,就将2添加到hash中,此时hash=[2],当a=5时,b=2,由于hash中已经存在2,说明2与5正好达成一个匹配,由于题目说明只存在一个答案,否则我们还要将2弹出去,避免出现[2,5,5],返回[[2,5],[2,5]]这样的结果。
 

    class Solution:
        def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        mydict ={}
        for i in range(len(nums)):
            num =target-nums[i] 
            if num not in mydict:
                mydict[nums[i]]=i
            else:
                return [mydict[num],i]





----------
三数之和

> 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

> 注意:答案中不可以包含重复的三元组。

> 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

> 满足要求的三元组集合为:
> [
>   [-1, 0, 1],
>   [-1, -1, 2]
> ]

思路:

想要找到满足a+b+c=0的元素,等价于找到a+b=-c的元素,最简单的思路是三层循环遍历求解,但是由于其高额的时间复杂度,是我们无法承担的,所以采用一种O(n**2)的方法,减少时间消耗。---双指针法


先排序,从小大,两层循环,外层循环遍历nums = [-1, -1,0, 1, 2, -4],依次取出其中的元素作为-c,因此原题就转化为了在列表nums中寻找其他两个**不同**的元素使得a+b=-c。**为什么要排序呢?这里解释一下,先进行从小到大的排序,那么每次取出一个元素,我们假设这是取出的三个数中的最小的元素,那么为了满足等式要求,就需要找到另外两个较大的数,而这两个较大的数,此时必然在列表的右边,这样一来,就不需要经历从头到尾的遍历了。**内层循环设立两个指针,分别指向-c的下一位与列表最后一位(**较大的两个数**)当a大于0的时候,a,b,c就都大于0了,此时应该结束寻找。通过上述多次剪枝,我们大大降低了算法的执行时间。
 

    class Solution:
        def threeSum(self, nums):
            """
            a+b+c =0 ==> a+b = -c
            双指针法,fix 一个数,用双指针法去寻找另外两个数
            两个指针分别指向,fix数字之后开始的数组首尾两个数
            两数之和大于target,右边的指针左移一位
            两数之和小于target,左边的指针右移一位
            +剪枝优化:假设当前的target大于0 ,那么break
            假设当前target的值与前面target的值相等那么退出本次循环,
            赋值会大大增加程序运行时间
    
            """


            length =len(nums)
            res =[]
            if length>2:
    
                nums =sorted(nums)
    
                for i in range(length-2):
                    target= nums[i]
                    if target>0:
                        break
                    if i>0 and nums[i]==nums[i-1]:
                        continue
                    left =i+1
                    right =length-1
                    while left<right:
                        val =nums[right]+nums[left]
                        if val==-target:
                            res.append([target,nums[left],nums[right]])
                            #相同的元素忽略,以免返回重复的结果
                            while left<right and nums[left]==nums[left+1]:
                                left+=1
                            while left<right and nums[right]==nums[right-1]:
                                right-=1
                            left+=1
                            right-=1
                        elif val>-target:
                            right-=1
                        else:
                            left+=1
                return res
            else:
                return res

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值