返回介绍

solution / 0000-0099 / 0015.3Sum / README_EN

发布于 2024-06-17 01:04:40 字数 11908 浏览 0 评论 0 收藏 0

15. 3Sum

中文文档

Description

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.

 

Example 1:

Input: nums = [-1,0,1,2,-1,-4]
Output: [[-1,-1,2],[-1,0,1]]
Explanation: 
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.
The distinct triplets are [-1,0,1] and [-1,-1,2].
Notice that the order of the output and the order of the triplets does not matter.

Example 2:

Input: nums = [0,1,1]
Output: []
Explanation: The only possible triplet does not sum up to 0.

Example 3:

Input: nums = [0,0,0]
Output: [[0,0,0]]
Explanation: The only possible triplet sums up to 0.

 

Constraints:

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

Solutions

Solution 1: Sort + Two Pointers

We notice that the problem does not require us to return the triplet in order, so we might as well sort the array first, which makes it easy to skip duplicate elements.

Next, we enumerate the first element of the triplet $nums[i]$, where $0 \leq i \lt n - 2$. For each $i$, we can find $j$ and $k$ satisfying $nums[i] + nums[j] + nums[k] = 0$ by maintaining two pointers $j = i + 1$ and $k = n - 1$. In the enumeration process, we need to skip duplicate elements to avoid duplicate triplets.

The specific judgment logic is as follows:

If $i \gt 0$ and $nums[i] = nums[i - 1]$, it means that the element currently enumerated is the same as the previous element, we can skip it directly, because it will not produce new results.

If $nums[i] \gt 0$, it means that the element currently enumerated is greater than $0$, so the sum of three numbers must not be equal to $0$, and the enumeration ends.

Otherwise, we let the left pointer $j = i + 1$, and the right pointer $k = n - 1$. When $j \lt k$, the loop is executed, and the sum of three numbers $x = nums[i] + nums[j] + nums[k]$ is calculated and compared with $0$:

  • If $x \lt 0$, it means that $nums[j]$ is too small, we need to move $j$ to the right.
  • If $x \gt 0$, it means that $nums[k]$ is too large, we need to move $k$ to the left.
  • Otherwise, it means that we have found a valid triplet, add it to the answer, move $j$ to the right, move $k$ to the left, and skip all duplicate elements to continue looking for the next valid triplet.

After the enumeration is over, we can get the answer to the triplet.

The time complexity is $O(n^2)$, and the space complexity is $O(\log n)$. The $n$ is the length of the array.

class Solution:
  def threeSum(self, nums: List[int]) -> List[List[int]]:
    nums.sort()
    n = len(nums)
    ans = []
    for i in range(n - 2):
      if nums[i] > 0:
        break
      if i and nums[i] == nums[i - 1]:
        continue
      j, k = i + 1, n - 1
      while j < k:
        x = nums[i] + nums[j] + nums[k]
        if x < 0:
          j += 1
        elif x > 0:
          k -= 1
        else:
          ans.append([nums[i], nums[j], nums[k]])
          j, k = j + 1, k - 1
          while j < k and nums[j] == nums[j - 1]:
            j += 1
          while j < k and nums[k] == nums[k + 1]:
            k -= 1
    return ans
class Solution {
  public List<List<Integer>> threeSum(int[] nums) {
    Arrays.sort(nums);
    List<List<Integer>> ans = new ArrayList<>();
    int n = nums.length;
    for (int i = 0; i < n - 2 && nums[i] <= 0; ++i) {
      if (i > 0 && nums[i] == nums[i - 1]) {
        continue;
      }
      int j = i + 1, k = n - 1;
      while (j < k) {
        int x = nums[i] + nums[j] + nums[k];
        if (x < 0) {
          ++j;
        } else if (x > 0) {
          --k;
        } else {
          ans.add(List.of(nums[i], nums[j++], nums[k--]));
          while (j < k && nums[j] == nums[j - 1]) {
            ++j;
          }
          while (j < k && nums[k] == nums[k + 1]) {
            --k;
          }
        }
      }
    }
    return ans;
  }
}
class Solution {
public:
  vector<vector<int>> threeSum(vector<int>& nums) {
    sort(nums.begin(), nums.end());
    vector<vector<int>> ans;
    int n = nums.size();
    for (int i = 0; i < n - 2 && nums[i] <= 0; ++i) {
      if (i && nums[i] == nums[i - 1]) {
        continue;
      }
      int j = i + 1, k = n - 1;
      while (j < k) {
        int x = nums[i] + nums[j] + nums[k];
        if (x < 0) {
          ++j;
        } else if (x > 0) {
          --k;
        } else {
          ans.push_back({nums[i], nums[j++], nums[k--]});
          while (j < k && nums[j] == nums[j - 1]) {
            ++j;
          }
          while (j < k && nums[k] == nums[k + 1]) {
            --k;
          }
        }
      }
    }
    return ans;
  }
};
func threeSum(nums []int) (ans [][]int) {
  sort.Ints(nums)
  n := len(nums)
  for i := 0; i < n-2 && nums[i] <= 0; i++ {
    if i > 0 && nums[i] == nums[i-1] {
      continue
    }
    j, k := i+1, n-1
    for j < k {
      x := nums[i] + nums[j] + nums[k]
      if x < 0 {
        j++
      } else if x > 0 {
        k--
      } else {
        ans = append(ans, []int{nums[i], nums[j], nums[k]})
        j, k = j+1, k-1
        for j < k && nums[j] == nums[j-1] {
          j++
        }
        for j < k && nums[k] == nums[k+1] {
          k--
        }
      }
    }
  }
  return
}
function threeSum(nums: number[]): number[][] {
  nums.sort((a, b) => a - b);
  const ans: number[][] = [];
  const n = nums.length;
  for (let i = 0; i < n - 2 && nums[i] <= 0; i++) {
    if (i > 0 && nums[i] === nums[i - 1]) {
      continue;
    }
    let j = i + 1;
    let k = n - 1;
    while (j < k) {
      const x = nums[i] + nums[j] + nums[k];
      if (x < 0) {
        ++j;
      } else if (x > 0) {
        --k;
      } else {
        ans.push([nums[i], nums[j++], nums[k--]]);
        while (j < k && nums[j] === nums[j - 1]) {
          ++j;
        }
        while (j < k && nums[k] === nums[k + 1]) {
          --k;
        }
      }
    }
  }
  return ans;
}
use std::cmp::Ordering;

impl Solution {
  pub fn three_sum(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
    nums.sort();
    let n = nums.len();
    let mut res = vec![];
    let mut i = 0;
    while i < n - 2 && nums[i] <= 0 {
      let mut l = i + 1;
      let mut r = n - 1;
      while l < r {
        match (nums[i] + nums[l] + nums[r]).cmp(&0) {
          Ordering::Less => {
            l += 1;
          }
          Ordering::Greater => {
            r -= 1;
          }
          Ordering::Equal => {
            res.push(vec![nums[i], nums[l], nums[r]]);
            l += 1;
            r -= 1;
            while l < n && nums[l] == nums[l - 1] {
              l += 1;
            }
            while r > 0 && nums[r] == nums[r + 1] {
              r -= 1;
            }
          }
        }
      }
      i += 1;
      while i < n - 2 && nums[i] == nums[i - 1] {
        i += 1;
      }
    }
    res
  }
}
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function (nums) {
  const n = nums.length;
  nums.sort((a, b) => a - b);
  const ans = [];
  for (let i = 0; i < n - 2 && nums[i] <= 0; ++i) {
    if (i > 0 && nums[i] === nums[i - 1]) {
      continue;
    }
    let j = i + 1;
    let k = n - 1;
    while (j < k) {
      const x = nums[i] + nums[j] + nums[k];
      if (x < 0) {
        ++j;
      } else if (x > 0) {
        --k;
      } else {
        ans.push([nums[i], nums[j++], nums[k--]]);
        while (j < k && nums[j] === nums[j - 1]) {
          ++j;
        }
        while (j < k && nums[k] === nums[k + 1]) {
          --k;
        }
      }
    }
  }
  return ans;
};
public class Solution {
  public IList<IList<int>> ThreeSum(int[] nums) {
    Array.Sort(nums);
    int n = nums.Length;
    IList<IList<int>> ans = new List<IList<int>>();
    for (int i = 0; i < n - 2 && nums[i] <= 0; ++i) {
      if (i > 0 && nums[i] == nums[i - 1]) {
        continue;
      }
      int j = i + 1, k = n - 1;
      while (j < k) {
        int x = nums[i] + nums[j] + nums[k];
        if (x < 0) {
          ++j;
        } else if (x > 0) {
          --k;
        } else {
          ans.Add(new List<int> { nums[i], nums[j--], nums[k--] });
          while (j < k && nums[j] == nums[j + 1]) {
            ++j;
          }
          while (j < k && nums[k] == nums[k + 1]) {
            --k;
          }
        }
      }
    }
    return ans;
  }
}
# @param {Integer[]} nums
# @return {Integer[][]}
def three_sum(nums)
  res = []
  nums.sort!

  for i in 0..(nums.length - 3)
  next if i > 0 && nums[i - 1] == nums[i]
  j = i + 1
  k = nums.length - 1
  while j < k do
    sum = nums[i] + nums[j] + nums[k]
    if sum < 0
    j += 1
    elsif sum > 0
    k -= 1
    else
    res += [[nums[i], nums[j], nums[k]]]
    j += 1
    k -= 1
    j += 1 while nums[j] == nums[j - 1]
    k -= 1 while nums[k] == nums[k + 1]
    end
  end
  end

  res
end
class Solution {
  /**
   * @param int[] $nums
   * @return int[][];
   */

  function threeSum($nums) {
    $result = [];
    $n = count($nums);

    sort($nums);
    for ($i = 0; $i < $n - 2; $i++) {
      if ($i > 0 && $nums[$i] === $nums[$i - 1]) {
        continue;
      }

      $left = $i + 1;
      $right = $n - 1;

      while ($left < $right) {
        $sum = $nums[$i] + $nums[$left] + $nums[$right];

        if ($sum === 0) {
          $triplet = [$nums[$i], $nums[$left], $nums[$right]];
          $result[] = $triplet;

          while ($left < $right && $nums[$left] === $nums[$left + 1]) {
            $left++;
          }

          while ($left < $right && $nums[$right] === $nums[$right - 1]) {
            $right--;
          }

          $left++;
          $right--;
        } elseif ($sum < 0) {
          $left++;
        } else {
          $right--;
        }
      }
    }

    return $result;
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文