Skip to content
RSS feed tkhwang on GitHub tkhwang on Twitter

πŸ€– leetcode 15. 3Sum | medium | two-pointer | javascript

πŸ—’οΈ Problems

3Sum - LeetCode

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.
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.

two sum에 이은 three sum 문제.

✨ Idea

  • nums μ—μ„œ ν•˜λ‚˜μ˜ 숫자(value)λ₯Ό μ„ νƒν•˜κ³ , 쀑볡을 ν”Όν•˜κΈ° μœ„ν•΄μ„œ 이후 였λ₯Έμͺ½ λ‚˜λ¨Έμ§€ array μ—μ„œ twoSum을 μ΄μš©ν•΄μ„œ μ•žμ˜ μ„ νƒλœ -value λ₯Ό μ°ΎλŠ”λ‹€.
  • twoSum λ¬Έμ œλŠ” sorted arrayμ—μ„œ two pointers κΈ°λ²•μœΌλ‘œ μ°ΎλŠ”λ‹€.
  • μ€‘λ³΅λ˜λŠ” μˆ«μžμ— λŒ€ν•œ μ²˜λ¦¬κ°€ μ–΄λ €μ› λŠ”λ°, labuladong의 쒋은 책에 쒋은 방법이 λ‚˜μ™€μ„œ μ •λ¦¬ν•΄λ΄…λ‹ˆλ‹€.

πŸ€ Intuition

숫자 ν•˜λ‚˜ ([object Object]) 선택 ν›„ twoSum 으둜 [object Object] κ°’ μ°ΎκΈ°

  • twoSum 을 left-right two pointers 기법 μ‚¬μš©ν•˜κΈ° μœ„ν•˜μ—¬ nums μ •λ ¬.
nums.sort((a, b) => a - b);

for (let i = 0; i < N; i += 1) {
  const cur = nums[i];

  twoSum(i + 1, N - 1, -cur);
}

sorted arrayμ—μ„œ left-right two pointers μ΄μš©ν•œ two sum

Two Sum II - Input Array Is Sorted - LeetCode

nums.sort((a,b) => a - b);
...
    const twoSum = (left, right, target) => {
        while (left < right) {
            const sum = nums[left] + nums[right];

            if (sum > target) {
                right -= 1;
            } else if (sum < target) {
                left += 1;
            } else if (sum === target) {
                return [ left, right ] ;
            }
        }
    }
    return [ -1, -1]

πŸ’‘ μΌλ°˜ν™”λœ two sum 의 left-right two pointers 기법

μ€‘λ³΅λœ κ°’μ˜ κ²½μš°μ—λŠ” skip ν•˜λ„λ‘ 처리 좔가함.

  leftValue       rightValue
    |                 |
... 2  2   ...    3   3
    |                 |
   left ->        <- right
  • left ν¬μΈν„°μ˜ 값이 λ°”λ€”λ•ŒκΉŒμ§€ 계속 증가
while (left < right && nums[left] === leftValue) left += 1;
  • right ν¬μΈν„°μ˜ 값이 λ°”λ€”λ•ŒκΉŒμ§€ 계속 감속
while (left < right && nums[right] === rightValue) right -= 1;
const twoSum = (left, right, target) => {
  while (left < right) {
    const leftValue = nums[left];
    const rightValue = nums[right];

    const sum = leftValue + rightValue;

    if (sum > target) {
      while (left < right && nums[right] === rightValue) right -= 1;
    } else if (sum < target) {
      while (left < right && nums[left] === leftValue) left += 1;
    } else if (sum === target) {
      res.push([-target, nums[left], nums[right]]);
      while (left < right && nums[right] === rightValue) right -= 1;
      while (left < right && nums[left] === leftValue) left += 1;
    }
  }
};

πŸ’‘ 졜초 κ°’ 선택 μ‹œμ—λ„ 쀑볡 처리 처리 μΆ”κ°€

μ•žμ—μ„œ μ„ νƒν•œ 값이 λ™μΌν•œ κ²½μš°μ—λŠ” skip 처리 μΆ”κ°€

for (let i = 0; i < N; i += 1) {
  const cur = nums[i];

  twoSum(i + 1, N - 1, -cur);

  while (i < N && nums[i] === nums[i + 1]) i += 1;
}

πŸ”₯ My Solution

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function (nums) {
  const N = nums.length;

  nums.sort((a, b) => a - b);

  const res = [];

  const twoSum = (left, right, target) => {
    while (left < right) {
      const leftValue = nums[left];
      const rightValue = nums[right];

      const sum = leftValue + rightValue;

      if (sum > target) {
        while (left < right && nums[right] === rightValue) right -= 1;
      } else if (sum < target) {
        while (left < right && nums[left] === leftValue) left += 1;
      } else if (sum === target) {
        res.push([-target, nums[left], nums[right]]);
        while (left < right && nums[right] === rightValue) right -= 1;
        while (left < right && nums[left] === leftValue) left += 1;
      }
    }
  };

  for (let i = 0; i < N; i += 1) {
    const cur = nums[i];

    twoSum(i + 1, N - 1, -cur);

    while (i < N && nums[i] === nums[i + 1]) i += 1;
  }

  return res;
};