背景
本篇图文是LSGO软件技术团队组织的 第二期基础算法(Leetcode)刻意练习训练营 的打卡任务。本期训练营采用分类别练习的模式,即选择了五个知识点(数组、链表、字符串、树、贪心算法),每个知识点选择了 三个简单、两个中等、一个困难 等级的题目,共计三十道题,利用三十天的时间完成这组刻意练习。
本次任务的知识点:数组
数组 是在程序设计中,为了处理方便,把具有相同类型的若干元素按有序的形式组织起来的一种形式。抽象地讲,数组即是有限个类型相同的元素的有序序列。若将此序列命名,那么这个名称即为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素。而用于区分数组的各个元素的数字编号则被称为下标,若为此定义一个变量,即为下标变量。
题目
给定一个包含n
个整数的数组nums
,判断nums
中是否存在三个元素a,b,c
,使得a + b + c = 0
?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
实现
第一种:三指针法
思路:为了避免三次循环,提升执行效率。首先对nums
进行排序,复杂度为 O(NlogN)。然后固定3个指针i,l(left),r(right)
,i
进行最外层循环,l
指向nums[i]
之后数组的最小值,r
指向nums[i]
之后数组的最大值。模仿快速排序的思路,如果nums[i] > 0
就不需要继续计算了,否则计算nums[i] + nums[l] + nums[r]
是否等于零并进行相应的处理。如果大于零,向l
方向移动r
指针,如果小于零,向r
方向移动l
指针,如果等于零,则加入到存储最后结果的result链表中。当然,题目中要求这个三元组不可重复,所以在进行的过程中加入去重就好。
- 执行结果:通过
- 执行用时:348 ms, 在所有 C# 提交中击败了 99.54% 的用户
- 内存消耗:35.8 MB, 在所有 C# 提交中击败了 6.63% 的用户
public class Solution
{
public IList<IList<int>> ThreeSum(int[] nums)
{
IList<IList<int>> result = new List<IList<int>>();
nums = nums.OrderBy(a => a).ToArray();
int len = nums.Length;
for (int i = 0; i < len - 2; i++)
{
if (nums[i] > 0)
break; // 如果最小的数字大于0, 后面的操作已经没有意义
if (i > 0 && nums[i - 1] == nums[i])
continue; // 跳过三元组中第一个元素的重复数据
int l = i + 1;
int r = len - 1;
while (l < r)
{
int sum = nums[i] + nums[l] + nums[r];
if (sum < 0)
{
l++;
}
else if (sum > 0)
{
r--;
}
else
{
result.Add(new List<int>() {nums[i], nums[l], nums[r]});
// 跳过三元组中第二个元素的重复数据
while (l < r && nums[l] == nums[l + 1])
{
l++;
}
// 跳过三元组中第三个元素的重复数据
while (l < r && nums[r - 1] == nums[r])
{
r--;
}
l++;
r--;
}
}
}
return result;
}
}
Python 语言
- 执行结果:通过
- 执行用时:660 ms, 在所有 Python3 提交中击败了 95.64% 的用户
- 内存消耗:16.1 MB, 在所有 Python3 提交中击败了 75.29% 的用户
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums = sorted(nums)
result = []
for i in range(0, len(nums) - 2):
# 如果最小的数字大于0, 后面的操作已经没有意义
if nums[i] > 0:
break
# 跳过三元组中第一个元素的重复数据
if i > 0 and nums[i-1] == nums[i]:
continue
# 限制nums[i]是三元组中最小的元素
l = i + 1
r = len(nums) - 1
while l < r:
sum = nums[i] + nums[l] + nums[r]
if sum < 0:
l += 1
elif sum > 0:
r -= 1
else:
result.append([nums[i], nums[l], nums[r]])
# 跳过三元组中第二个元素的重复数据
while l < r and nums[l] == nums[l+1]:
l += 1
# 跳过三元组中第三个元素的重复数据
while l < r and nums[r] == nums[r-1]:
r -= 1
l += 1
r -= 1
return result
来源
- https://leetcode-cn.com/problems/3sum/solution/3sumpai-xu-shuang-zhi-zhen-yi-dong-by-jyd/
往期活动
LSGO软件技术团队会定期开展提升编程技能的刻意练习活动,希望大家能够参与进来一起刻意练习,一起学习进步!
- Python基础刻意练习活动即将开启,你参加吗?
- Task01:变量、运算符与数据类型
- Task02:条件与循环
- Task03:列表与元组
- Task04:字符串与序列
- Task05:函数与Lambda表达式
- Task06:字典与集合
- Task07:文件与文件系统
- Task08:异常处理
- Task09:else 与 with 语句
- Task10:类与对象
- Task11:魔法方法
- Task12:模块
我是 终身学习者“老马”,一个长期践行“结伴式学习”理念的 中年大叔。
我崇尚分享,渴望成长,于2010年创立了“LSGO软件技术团队”,并加入了国内著名的开源组织“Datawhale”,也是“Dre@mtech”、“智能机器人研究中心”和“大数据与哲学社会科学实验室”的一员。
愿我们一起学习,一起进步,相互陪伴,共同成长。
后台回复「搜搜搜」,随机获取电子资源!
欢迎关注,请扫描二维码: