两数之和 & 三数之和(数组)

两数之和

  • 最初做法:两个for循环进行一个一个的试错,直到遇到符合条件的,返回。这个程序的时间复杂度是 n 2 n^2 .
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        returnList = []
        for i in range(len(nums)):
            for j in range(len(nums)):
                if i != j:
                    if(nums[i] + nums[j] == target):
                        returnList.append(i)
                        returnList.append(j)
                        return returnList       

在这里插入图片描述

  • 提示:解题关键主要是想找到num2 = target - num1是否也在nums中,然后再返回其对应的索引。所以,第二个数字通过num2 = target - num1找到,而不再是使用第二个for循环。
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(0, len(nums)):
            another = target - nums[i]
            if another in nums:
                if i != nums.index(another):
                    return [i, nums.index(another)]
        print('没有结果')

在这里插入图片描述

  • 提示:上面的做法是每次都从nums中找出第二个数,但实际上我们可以缩小查找范围,只需要从num1后的位置进行查找~因为位于其前面的数,如果有符合的,早就已经返回了。
        for i in range(0, len(nums)):
            another = target - nums[i]
            if another in nums[i+1:]:
                return [i, nums[i+1:].index(another)+(i+1)]
        print('没有结果')
  • 执行时间并没有加快很多…毕竟时间复杂度是同一个等级的,所以还是要想其他方法…
    在这里插入图片描述
  • 提示:通过字典来模拟哈希查询的过程。

enumerate()函数:用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据下标和数据; 返回 enumerate(枚举) 对象。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashmap={}
        for index, num in enumerate(nums): # 将索引以及对应的值存储在一个字典中
            hashmap[num] = index
        for i, n in enumerate(nums):
            j = hashmap.get(target - n)
            if j is not None and i!=j:
                return [i,j]

在这里插入图片描述

  • 提示:上面程序先将所有值以及对应的索引保存在hashmao中,然后再次循环enumerate(nums),从hashmap字典中查找指定的值;但实际上,我们仍然不需要在整个hashmap字典中进行查找。下面是改进的程序,我认为它是“从后往前”查找出指定的数的。
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashmap = {} 
        for index, num in enumerate(nums): 
            num2 = target - num
            if num2 in hashmap:
                return [index, hashmap[num2]]
            hashmap[num] = index # num是键,index是值

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

三数之和

参考:https://leetcode-cn.com/problems/3sum/solution/3sumpai-xu-shuang-zhi-zhen-yi-dong-by-jyd/

  • 暴力法解决的时间复杂度为 O ( n 3 ) O(n^3) ,具体算法略。
  • 除了以上的方法,我并没有想出其他解法。于是看了其他人的笔记——使用 “双指针” ,这里进行记录。
    假设nums数组如下:
    在这里插入图片描述
    Step1、将给定的nums数组进行排序(升序)
    在这里插入图片描述
    Step2、固定三个指针中的一个指针k到索引最小处,然后另外两个指针lr分别固定在除了k指向的位置之外的最左侧与最右侧。
    在这里插入图片描述
    在这里插入图片描述
    Step3、双指针lr交替中间移动,记录对于每个固定指针k的所有满足nums[k] + nums[l] + nums[r] == 0lr组合。然而,并不是简单地直接进行算法的书写就可以了,因为我们要分析出详尽的步骤以及特殊情况:
    在这里插入图片描述

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


程序如下(Python实现):

def threeSum(nums):
    """
    :type nums: List[int]
    :rtype: List[List[int]]
    """
    nums.sort() # 原地升序排序
    result, k = [], 0 # k,l,r三个“指针”用索引来表示
    for k in range(len(nums) - 2):
    	if nums[k] > 0:
    		break
    	if k > 0 and nums[k] == nums[k-1]:
    		continue
    	l, r = k+1, len(nums) - 1
    	while l < r:
    		s = nums[k] + nums[l] + nums[r]
    		if s < 0:
    			l += 1
    			while l < r and nums[l] == nums[l-1]:
    				l += 1
    		elif s > 0:
    			r -= 1
    			while l < r and nums[r] == nums[r+1]:
    				r -= 1
    		else:
    			result.append([nums[k], nums[l], nums[r]])
    			# 因为已经得到了使和为0的三个值了,所以如果再只改变l或r都不可能再得到和为0的结果;
    			# 而正确的做法就是使r,l同时改变,同时仍进行while判断
    			l += 1
    			r -= 1
    			while l < r and nums[l] == nums[l-1]:
    				l += 1
    			while l < r and nums[r] == nums[r+1]:
    				r -= 1
    return result
print(threeSum([-1, 0, 1, 2, -1, -4]))

在这里插入图片描述

发布了53 篇原创文章 · 获赞 33 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/jy_z11121/article/details/101146012