数组中相加和为0的三元组c语言,LeetCode:在一个整型数组中找出三个数相加为0的组合...

About

今天是挑战LeetCode的第二天,我选择了一道中等难度的题,结果花了3个小时仍然未能通过所有的测试用例,主要是算法时间复杂度太大,超过了时间限制,下面将我的解题过程分享一下

三数之和

描述

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

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

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

满足要求的三元组集合为:

[

[-1, 0, 1],

[-1, -1, 2]

]

解题思路

为了避免答案重复,我先把数组进行了排序

遍历数组,先确定第一个值,求出diff = 0 - firstValue (遍历时如果有重复值就跳过)

然后遍历从第一个选中的值的位置切片后的数组, 求出 diff_another = secondValue - diff (遍历时如果有重复值就跳过)

在剩下的数组中查找 diff_another,如果能找到就说明有解。

为了提高查找效率,我选择了二分查找法。

代码

class Solution(object):

def binary_chop(self, array, data):

n = len(array)

first = 0

last = n - 1

while first <= last:

mid = (last + first) // 2

if array[mid] > data:

last = mid - 1

elif array[mid] < data:

first = mid + 1

else:

return True

return False

def threeSum(self, nums):

"""

:type nums: List[int]

:rtype: List[List[int]]

"""

nums.sort()

ans = []

for index in range(len(nums)):

if nums[index] > 0: break

if nums[index] == nums[index-1] and index > 0: continue

diff = 0 - nums[index]

for key in range(index+1, len(nums)):

if nums[key] > diff: break

if nums[key] == nums[key-1] and key > index + 1 : continue

diff_another = diff - nums[key]

if self.binary_chop(nums[key+1:], diff_another):

ans.append([nums[index], nums[key], diff_another])

return ans

运行结果

通过了311个测试用例,但是当测试用例的元素超过3000后,该算法运行时间超过14s,未能达到要求

参考算法

采用三个指针分别指向左边,中间,右边三个值,在运算的时候选择从两边向中间逼近,大幅减小了时间复杂度。

class Solution:

def threeSum(self, nums):

nums.sort()

res, k = [], 0

for k in range(len(nums) - 2):

if nums[k] > 0: break # because of j > i > k.

if k > 0 and nums[k] == nums[k - 1]: continue # skip.

i, j = k + 1, len(nums) - 1

while i < j:

s = nums[k] + nums[i] + nums[j]

if s < 0:

i += 1

while i < j and nums[i] == nums[i - 1]: i += 1

elif s > 0:

j -= 1

while i < j and nums[j] == nums[j + 1]: j -= 1

else:

res.append([nums[k], nums[i], nums[j]])

i += 1

j -= 1

while i < j and nums[i] == nums[i - 1]: i += 1

while i < j and nums[j] == nums[j + 1]: j -= 1

return res

参考链接

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值