qidao123.com技术社区-IT企服评测·应用市场

标题: 【逐日一题】LeetCode - 三数之和 [打印本页]

作者: 李优秀    时间: 2025-4-20 11:18
标题: 【逐日一题】LeetCode - 三数之和
给你一个整数数组 nums ,判定是否存在三元组 [nums, nums[j], nums[k]] 满意 i != j、i != k 且 j != k ,同时还满意 nums + nums[j] + nums[k] == 0 。请你返回全部和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例

示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:满意条件的三元组为 [-1, 0, 1] 和 [-1, -1, 2]。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0。
思绪分析

这个问题的焦点思绪是找到数组中的三个数,其和为 0,同时要避免重复的组合。为了解决这个问题,我们可以通过排序和双指针的联合来有用地实现。
步骤:

这个思绪使得代码在处理每个三元组时,只计算不重复的组合。
实当代码

  1. class Solution {
  2. public:
  3.     vector<vector<int>> threeSum(vector<int>& nums) {
  4.         vector<vector<int>> ans;
  5.         sort(nums.begin(), nums.end());  // 第一步:排序数组
  6.         for(int a = 0; a < nums.size(); a++) {
  7.             if(nums[a] > 0) break;  // 如果当前数大于0,跳出循环,因为后面的数都更大,不可能和为0
  8.             if(a > 0 && nums[a] == nums[a - 1]) continue;  // 避免重复
  9.             // 初始化双指针
  10.             int left = a + 1, right = nums.size() - 1;
  11.             while(left < right) {
  12.                 int sum = nums[a] + nums[left] + nums[right];
  13.                 if(sum == 0) {
  14.                     ans.push_back({nums[a], nums[left], nums[right]});
  15.                     // 移动指针避免重复
  16.                     while(left < right && nums[left] == nums[left + 1]) left++;
  17.                     while(left < right && nums[right] == nums[right - 1]) right--;
  18.                     left++;
  19.                     right--;
  20.                 } else if(sum < 0) {
  21.                     left++;
  22.                 } else {
  23.                     right--;
  24.                 }
  25.             }
  26.         }
  27.         return ans;
  28.     }
  29. };
复制代码
代码讲解

时空复杂度分析



比较其他实现方式

一种直接的实现方式是三重循环,但这样会导致 O(n^3) 的时间复杂度,效率低下。而双指针配合排序的实现方法可以有用地淘汰时间复杂度到 O(n^2),在大数据量情况下具有显著的性能优势。
总结

通过排序和双指针联合,我们可以高效地解决三数之和问题。该方法不但能避免重复,还能在 O(n^2) 的时间内找到全部符合条件的三元组,是一种简洁且高效的解法。
暴力破解实现

除了使用双指针的方法,我们还可以采用暴力破解的方法来解决这个问题。暴力破解的思绪就是通过三重循环罗列全部可能的三元组,检查其和是否为零。固然这种方法简单易懂,但效率较低。下面是暴力破解的实当代码:
  1. class Solution {
  2. public:
  3.     vector<vector<int>> threeSum(vector<int>& nums) {
  4.         vector<vector<int>> ans;
  5.         for (int i = 0; i < nums.size(); i++) {
  6.             for (int j = i + 1; j < nums.size(); j++) {
  7.                 for (int k = j + 1; k < nums.size(); k++) {
  8.                     if (nums[i] + nums[j] + nums[k] == 0) {
  9.                         vector<int> triplet = {nums[i], nums[j], nums[k]};
  10.                         // 检查三元组是否已存在于答案中
  11.                         if (find(ans.begin(), ans.end(), triplet) == ans.end()) {
  12.                             ans.push_back(triplet);
  13.                         }
  14.                     }
  15.                 }
  16.             }
  17.         }
  18.         return ans;
  19.     }
  20. };
复制代码
代码讲解

时空复杂度分析



总结比较

暴力破解法固然简单直观,但对于大规模数据,效率低下。而通过排序与双指针的方法,可以将时间复杂度降低至 O(n^2),适用于大数据场景。因此,在实际应用中,保举使用双指针的方法解决三数之和问题。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4