跳转至

2022-11-24 三数之和

力扣题目:Link

双指针法重现

这一题采用双指针法会比hash_map 舒服一些。

打印二维数组

我按照leetcode的格式打印了二维数组,记得在每个元素/元组之间加逗号,而不在最后多添加的技术要点是:在输出完元素/元组后进行判断,如果打印的元素/元组不是最后一个,则打印一个逗号。

代码实现

/* LeetCode Question No.15
 * Given an integer array nums, return all the triplets `nums[i], nums[j], 
 * nums[k]` such that `i != j`, `i != k`, and `j != k`, and 
 * `nums[i] + nums[j] + nums[k] == 0`.
 *
 * Notice that the solution set must not contain duplicate triplets.
 */

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution{
public:
    vector<vector<int>> threeSum(vector<int>& nums){
        vector<vector<int>> result;
        sort(nums.begin(), nums.end()); // sort() need <algorithm>

        // 找出 a+b+c=0
        // a=nums[i], b=nums[left], c=nums[right]

        for (int i = 0; i < nums.size(); i++){

            // 排序之后如果第一个元素已经大于0,
            // 那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 
            if (nums[i] > 0){
                return result;
            }

            // 正确的去重方法
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }

            int left = i + 1;
            int right = nums.size() - 1;

            while (right > left) {
                // 如果去重复逻辑放在这里,则可能导致 left <= right
                // 从而漏掉了[0, 0, 0]元组

                if (nums[i] + nums[left] + nums[right] > 0) {
                    right--;
                } else if (nums[i] + nums[left] + nums[right] < 0) {
                    left++;
                } else {
                    result.push_back(
                        vector<int>{nums[i], nums[left], nums[right]});


                while (right > left && nums[right] == nums[right-1]) right++;
                while (right > left && nums[left] == nums[left+1]) left++;

                // 找到答案时,双指针同时收缩                
                right--;
                left++;
                }
            }
        } 
        return result;
    }
    void printV2D(vector<vector<int>>& nums) {

        cout << "[";
        for (vector<vector<int>>::iterator i = nums.begin(); 
             i != nums.end(); 
             i++){

            cout << "[";
            for (vector<int>::iterator j = i->begin();
                 j != i->end();
                 j++){
                cout << *j;
                // 每个元素之间打印一个逗号,最后一个元素不打印
                if (j != i->end()-1) cout << ",";
            }
            cout << "]";
            // 每个元组之间打印一个逗号,最后一个元组不打印
            if (i != nums.end()-1) cout << ",";
        }
        cout << "]" << endl;
    }
};

int main(void){
    vector<int> nums = {-1, 0, 1, 2, -1, -4};
    vector<vector<int>> result;

    // cin >> nums;

    Solution sl;

    result = sl.threeSum(nums);
    sl.printV2D(result);
}