0
点赞
收藏
分享

微信扫一扫

15. 三数之和(双指针法)(Leetcode刷题笔记)

东林梁 2022-02-06 阅读 30

15. 三数之和(双指针法)(Leetcode刷题笔记)

https://lunan0320.cn

文章目录

题目

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

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

解题代码 C++(核心代码)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        //先排序
        sort(nums.begin(),nums.end());
        //nums[i]  nums[left] nums[right]
        for(int i = 0; i < nums.size(); i++){
            //排序后,最左端大于0 直接排除
            if(nums[i] > 0) return res;
            //对i索引所在的值去重
            /*
            错误写法,这样会使得-1,-1,2的情况没有考虑进去
            if(i+1<nums.size() && nums[i] == nums[i+1]) continue;
            */
            if(i > 0 && nums[i] == nums[i-1]) continue;
            //每一次都要重新定义left和right
            int left = i + 1, right = nums.size()-1;
            while(right > left){
                if(nums[i] + nums[left] + nums[right] > 0){
                    right--;
                }else if(nums[i] + nums[left] + nums[right] < 0){
                    left++;
                }else{
                    //找到符合的值
                    res.push_back(vector<int>{nums[i],nums[left],nums[right]});
                    //去重,对于重复的可能组合去掉
                    //对于right一侧去重
                    while(right > left && nums[right] == nums[right-1]) right--;
                    //对于left一侧去重
                    while(right > left && nums[left] == nums[left+1]) left++;

                    //去重后重新赋值
                    right--;
                    left++;
                }
            }

        }
        return res;
    }
};

解题代码 C++(本地编译运行)

// head.h
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>

using namespace std;

//myHashMap.h
// 15题 双指针法
#include "head.h"

class ThreeSum {
public:
	vector<vector<int>> threeSum(vector<int>& nums) {
		vector<vector<int>> res;
		//对于数组nums排序,从小到大
		sort(nums.begin(), nums.end());
		//i是左端,依次遍历
		for (int i = 0; i < nums.size(); i++) {
			//终止的条件是有序数组的左端都大于0
			if (nums[i] > 0) return res;
			//对于索引i去重
			if (i > 0 && nums[i] == nums[i - 1]) continue;
			//定义left和right,此处不用判断i+1是否越界,因为下面会判断left和right的关系
			int left = i + 1, right = nums.size()-1;
			//每一次对left和right缩小收敛
			while (right > left) {
				//三数之和过大 则right收敛
				if (nums[i] + nums[left] + nums[right] > 0) right--;
				//三数之和过小 则left收敛
				else if (nums[i] + nums[left] + nums[right] < 0) left++;
				else {
					res.push_back(vector<int>{nums[i], nums[left], nums[right]});
					//对于right侧去重
					while (right > left && nums[right] == nums[right - 1]) right--;
					//对于left侧去重
					while (right > left && nums[left] == nums[left + 1]) left++;
					//去重结束后,left和right都要更新
					right--;
					left++;
				}
			}
		}
		return res;
	}
};


//main.cpp
#include "myHashMap.h"

int main() {
	ThreeSum solution;
	vector<int> nums = { -1,0,1,2,-1,-4 };
	vector<vector<int>> res;
	res = solution.threeSum(nums);
	for (auto sub : res) {
		for (auto i : sub) {
			cout << i << " ";
		}
		cout << endl;
	}
	return 0;
}

算法效率

举报

相关推荐

0 条评论