15. 三数之和 - 力扣(LeetCode)

基本知识要求:

Java:方法、数组、集合、泛型、if else语句、while循环、Arrays.sort()、Arrays.asList()、逻辑运算符、自增自减运算符

Python: 方法、列表、sort()排序、集合、if else语句、while循环、逻辑运算符

题目: 

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

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

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

思路解析 :

为了找到所有和为0且不重复的三元组,我们可以首先对数组进行排序,然后使用三个指针(i, j, k)在排序后的数组上进行遍历。

以下是解决这个问题的步骤:

  1. 对数组 nums 进行排序。
  2. 遍历数组,使用指针 i 从头开始,表示三元组的第一个元素。
  3. 为了避免重复,我们需要在遍历过程中跳过所有与 nums[i] 相同的元素,直到找到一个不同的元素。
  4. 使用指针 j 从 i+1 开始,表示三元组的第二个元素。
  5. 使用指针 k 从数组末尾开始,表示三元组的第三个元素。
  6. 当 i < j < k 时,进行以下操作:
    • 如果 nums[i] + nums[j] + nums[k] == 0,则找到了一个三元组,将其添加到结果集中,并跳过所有与 nums[j] 和 nums[k] 相同的元素,继续寻找下一个三元组。
    • 如果 nums[i] + nums[j] + nums[k] < 0,则 j 需要向右移动以增大和。
    • 如果 nums[i] + nums[j] + nums[k] > 0,则 k 需要向左移动以减小和。
  7. 遍历结束后,返回结果集。

Java代码示例:

import java.util.ArrayList;  
import java.util.Arrays;  
import java.util.List;  
  
public class Solution {  
  
    /**  
     * 找到数组中所有和为0的三元组  
     *  
     * @param nums 整数数组  
     * @return 所有和为0的三元组列表  
     */  
    public List<List<Integer>> threeSum(int[] nums) {  
        List<List<Integer>> result = new ArrayList<>(); // 存储结果的三元组列表  
        Arrays.sort(nums); // 对数组进行排序,以便使用双指针法  
  
        // 遍历数组,i为三元组的第一个元素  
        for (int i = 0; i < nums.length - 2; i++) {  
            // 跳过所有与nums[i]相同的元素,避免重复的三元组  
            if (i > 0 && nums[i] == nums[i - 1]) {  
                continue;  
            }  
  
            // j为三元组的第二个元素,初始位置为i+1  
            int j = i + 1;  
            // k为三元组的第三个元素,初始位置为数组末尾  
            int k = nums.length - 1;  
  
            // 当j < k时,进行内层循环  
            while (j < k) {  
                // 计算当前三个元素的和  
                int sum = nums[i] + nums[j] + nums[k];  
  
                if (sum == 0) {  
                    // 如果和为0,则找到一个三元组,添加到结果中  
                    result.add(Arrays.asList(nums[i], nums[j], nums[k]));  
  
                    // 跳过所有与nums[j]相同的元素  
                    while (j < k && nums[j] == nums[j + 1]) {  
                        j++;  
                    }  
  
                    // 跳过所有与nums[k]相同的元素  
                    while (j < k && nums[k] == nums[k - 1]) {  
                        k--;  
                    }  
  
                    // 继续寻找下一个三元组  
                    j++;  
                    k--;  
                } else if (sum < 0) {  
                    // 如果和小于0,则增加j的值,以增大和  
                    j++;  
                } else {  
                    // 如果和大于0,则减小k的值,以减小和  
                    k--;  
                }  
            }  
        }  
  
        // 返回结果  
        return result;  
    }  
  
    public static void main(String[] args) {  
        Solution solution = new Solution();  
        int[] nums = {-1, 0, 1, 2, -1, -4};  
        List<List<Integer>> triplets = solution.threeSum(nums);  
  
        // 输出所有找到的三元组  
        for (List<Integer> triplet : triplets) {  
            System.out.println(triplet);  
        }  
    }  
}

Python代码示例: 

def three_sum(nums):  
    # 先对数组进行排序  
    nums.sort()  
    triplets = []  
    n = len(nums)  
  
    # 遍历数组,从第一个元素开始  
    for i in range(n - 2):  
        # 跳过重复的元素  
        if i > 0 and nums[i] == nums[i - 1]:  
            continue  
  
        # 使用双指针法来寻找剩下的两个数  
        j = i + 1  
        k = n - 1  
        while j < k:  
            current_sum = nums[i] + nums[j] + nums[k]  
  
            if current_sum == 0:  
                # 找到一个三元组,将其添加到结果中  
                triplets.append([nums[i], nums[j], nums[k]])  
                # 跳过所有重复的元素  
                while j < k and nums[j] == nums[j + 1]:  
                    j += 1  
                while j < k and nums[k] == nums[k - 1]:  
                    k -= 1  
                j += 1  
                k -= 1  
            elif current_sum < 0:  
                # 如果和太小,则增加j  
                j += 1  
            else:  
                # 如果和太大,则减小k  
                k -= 1  
  
    return triplets  
  
# 示例  
nums = [-1, 0, 1, 2, -1, -4]  
print(three_sum(nums))  
# 输出:[[-1, -1, 2], [-1, 0, 1]]

这段代码定义了一个名为three_sum的函数,它接受一个整数数组nums作为输入,并返回所有和为0的不重复三元组的列表。函数首先对数组进行排序,然后使用三个指针(ijk)来遍历数组,并寻找满足条件的三元组。找到后,它使用两个内部循环来跳过所有重复的元素,以避免在结果中包含重复的三元组。最后,它返回找到的所有三元组的列表。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千小凡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值