Leetcode 三数之和-解题思路以及C++、java、python实现

本文介绍了如何使用双指针法解决给定整数数组中找到所有和为0的三元组的问题。通过排序数组,固定一个元素,然后用两个指针分别从两侧向中间移动,判断两数之和是否等于目标值,从而找到所有满足条件的三元组。文章提供了Python、C++和Java三种语言的实现代码。

15. 三数之和

题目描述:

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

示例:

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

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

解题思路(双指针解法):

三数之和转变成两数之和: a + b + c = 0 转成 a + b = -c。具体步骤:

1. 先对数组nums进行排序

2. 固定指针now是和c, 然后左指针从now前一个开始移动, hi指针从数组末端移动,

(1) nums[lo] + nums[hi] > nums[now] 则 hi指针向前移动1

(2) nums[lo] + nums[hi]  <  nums[now] 则 lo指针向后移动1

(3)  nums[lo] + nums[hi]  =  nums[now], 将这三个值存到结果数组results中, lo和 hi 向前移动1,如果移动后的nums[lo]和nums[hi] 还等于它们之前的值,就继续向前移动。这是去重操作。

(4) lo > hi 跳出这层循环。

如果nums[now] 大于0, 则直接跳出循环结束返回结果results数组。

python实现

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums.sort()
        nums_len = len(nums)
        results = []
        for i, sumi in enumerate(nums):
            if sumi > 0 :
                break
            if i > 0 and sumi == nums[i - 1]:
                continue
            negsum = 0 - sumi
            low = i + 1
            fast = nums_len - 1
            while(low < fast):
                if nums[low]  + nums[fast] > negsum:
                    fast -= 1
                elif  nums[low]  + nums[fast] < negsum:
                    low += 1
                else:
                    results.append([sumi, nums[low], nums[fast]])
                    left = nums[low]
                    right = nums[fast]
                    while(nums[low] == left and low < fast):
                        low += 1
                    while(nums[fast] == right and low < fast):
                        fast -= 1
        return results

C++实现

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int nums_len = nums.size();
        vector<vector<int>> results;
        int k=0;
        while(k < nums_len - 2){
            int c = nums[k];
            if(c > 0) break;
            int neg_c = 0 - c;
            int lo = k + 1;
            int hi = nums_len - 1;
            while(lo < hi){
                int a = nums[lo];
                int b = nums[hi];
                if(a + b > neg_c) hi--;
                else if(a + b < neg_c) lo++;
                else{
                    vector<int> result{c, a, b};
                    results.push_back(result);
                    while(nums[lo] == a && lo < hi) lo++;
                    while(nums[hi] == b && lo < hi) hi--;
                }
                
            }
            while(nums[k] == c && k < nums_len - 2) k++;
        }
        return results;
    }
};

java实现:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        int nums_len = nums.length;
        List<List<Integer>> results = new ArrayList();
        int k=0;
        while(k < nums_len - 2){
            int c = nums[k];
            if(c > 0) break;
            int neg_c = 0 - c;
            int lo = k + 1;
            int hi = nums_len - 1;
            while(lo < hi){
                int a = nums[lo];
                int b = nums[hi];
                if(a + b > neg_c) hi--;
                else if(a + b < neg_c) lo++;
                else{
                    List<Integer> result = new ArrayList();
                    result.add(c);
                    result.add(a);
                    result.add(b);
                    results.add(result);
                    while(nums[lo] == a && lo < hi) lo++;
                    while(nums[hi] == b && lo < hi) hi--;
                }
                
            }
            while(nums[k] == c && k < nums_len - 2) k++;
        }
        return results;
    }
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

TanH.blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值