双指针之两数之和,三数之和,N数之和系列

两数之和

暴力法,时间复杂度O(n*n),空间复杂度O(1)

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        for i in range(len(nums)):
            for j in range(i+1, len(nums)):
                if nums[i] + nums[j] == target:
                    return [i, j]
                

hashmap,时间复杂度O(n),空间复杂度O(n)

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hashmap = {}
        for index, num in enumerate(nums):
            res = target - num
            if res in hashmap:
                return [hashmap[res], index]
            hashmap[num] = index

二分查找,先排序,后双指针,排序时间复杂度为O(nlog(n)),双指针时间复杂度为O(n)
所以,总的时间复杂度为O(n
log(n))
该方法返回的是对应的数字,而不是数字索引,要想知道索引,需要保存原数组进行二次查找。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        nums = sorted(nums)
        n = len(nums)
        left = 0
        right = n - 1
        while left < right:
            s = nums[left] + nums[right]
            if s == target:
                return [nums[left], nums[right])]
            elif s < target:
                left += 1
            elif s > target:
                right -= 1
        

如果数组有重复数,并且存在多对数字和为target,代码如下

def twoSum(nums, target):
	nums.sort()
	n = len(nums)
	left = 0
	right = n - 1
	res = []
	while left < right:
		s = nums[left] + nums[right]
		lo = nums[left], hi = nums[right]
		if s < target:
			while left < right and nums[left] == lo:
				left += 1
		elif s > target:
			while left < right and nums[right] == hi:
				right -= 1
		else:
			res.append([lo, hi])
			while left < right and nums[left] == lo:
				left += 1
			while left < right and nums[right] == hi:
				right -= 1
	return res
			

三数之和

外层for循环遍历每一个数,内层变为求两数之和为target-nums[i]
排序时间复杂度为O(nlog(n)),外层for循环复杂度为O(n),双指针时间复杂度为O(n)
时间复杂度O(n
log(n) + nn)=O(nn)
注意跳过重复数

def threeSum(nums, target):
	nums.sort()
	n = len(nums)
	res = []
	i = 0
	while i < n:
		tuples = twoSum(nums, i + 1, target - nums[i])
		if not tuples:
			i += 1
			continue
		for t in tuples:
			res.append(t)
		i += 1
		while i < n and nums[i] == nums[i - 1]:
			i += 1
	return res
def twoSum(nums, start, target):
	left = start
	right = len(nums) - 1
	res = []
	while left < right:
		...(两数之和代码)
	return res

四数之和

外层for循环遍历每一个数,内层变为求三数之和为target-nums[i]
请读者自行发挥。

N数之和

def nSum(nums, n, start, target):
	size = len(nums)
	res = []
	# 至少是2 sum, 并且数组大小不应该小于n
	if n < 2 or size < n:
	return res
	if n == 2:
		left = start
		right = size - 1
		while left < right:
			s = nums[left] + nums[right]
			lo = nums[left]
			hi = nums[right]
			if s < target:
				while left < right and nums[left] == lo:
					left += 1
			elif s > target:
				while left < right and nums[right] == hi:
					right -= 1
			else:
				res.append([lo, hi])
				while left < right and nums[left] == lo:
					left += 1
				while left < right and nums[right] == hi:
					right -= 1
	else:
		# n > 2时,递归计算(n-1)sum的结果
		i = start
		while i < size:
			sub = nSum(nums, n - 1, i + 1, target - nums[i])
			# (n - 1) sum + nums[i]就是n sum
			for arr in sub:
				arr.append(nums[i])
				res.append(arr)
			i += 1
			while i < size and nums[i] = nums[i - 1]:
				i += 1
	return res
		
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值