Tried to coast on the wind of TwoSumII, but it didn’t quite work:

// i != j
// i != k
// j != k
// i !--- j
//        !
//        |
//        v
// i !--- k
// So none are the same
// And all added together are 0
// I could iterate through all values
// And find all possible two sums
// then check those 
function threeSum(nums: number[]): number[][] {
    let left = 0
    let right = 1
    const numMap: Map<number, number> = new Map()
    const results = []
 
    while (left < nums.length - 1){
        const sum = nums[left] + nums[right]
        if (numMap.has(sum)){
            results.push([left, right, sum])
        }
        numMap.set(nums[left], left)
        right++
        if (right >= nums.length){
            left++
            right=left+1
        }
    }
    return results
};

Haven’t figured out what’s going wrong here yet. I DID notice I wasn’t really checking if i, j and k were all different values, which the definition asks for. Here I am attempting to fix this:

// i != j
// i != k
// j != k
// i !--- j
//        !
//        |
//        v
// i !--- k
// So none are the same
// And all added together are 0
// I could iterate through all values
// And find all possible two sums
// then check those 
function threeSum(nums: number[]): number[][] {
    let left = 0
    let right = 1
    const numMap: Map<number, number> = new Map()
    const results = []
 
    for (let i = 0; i < nums.length; i++){
        numMap.set(nums[i], i)
    }
 
    while (left < nums.length - 1){
        const sum = nums[left] + nums[right]
        if (numMap.has(sum)){
            const sumIndex = numMap.get(sum)
            
            if (sum !== nums[left] && sum !== nums[right] && nums[right] !== nums[left]){
                results.push([left, right, sum])
            }
        }
 
        right++
        if (right >= nums.length){
            left++
            right=left+1
        }
    }
    return results
};

But this still doesn’t work. I’m going to try from the top - I feel that I should be able to get this to work.

I experimented a bit with console.logging the crap out of it:

function threeSum(nums: number[]): number[][] {
    let left = 0
    let right = 1
    const numMap = new Map()
    for (let i = 0; i < nums.length; i++){
        numMap.set(nums[i], i)
    }
    const results = []
 
    while (left < nums.length - 1){
 
        if (right >= nums.length){
            console.log(`right of ${right} is more than ${nums.length}, incrementing left from ${left} to ${left+1} and right to ${left + 2}`)
            left++
            right = left + 1
            continue
        }
 
        const negativeSum = (nums[left] + nums[right]) * -1
        console.log(`Negative sum of ${nums[left]} and ${nums[right]} is ${negativeSum}`)
        if (numMap.has(negativeSum)){
            const sumIndex = numMap.get(negativeSum)!
            console.log(`We found a negative sum at ${sumIndex} with value ${nums[sumIndex]}`)
            if (sumIndex !== left && sumIndex !== right){
                console.log(`left, right and sumindex are distinct: ${left},${right},${sumIndex}`)
                results.push([negativeSum, nums[left], nums[right]])
            } 
        }
 
        right++
    }
 
    return results
};

And this helped somehow. What I discovered was that I WAS actually getting all the right sets, it’s just that I was getting duplicate sets. So I’m gonna make sure that’s not happening anymore.

YES!!! I DID IT!!!

function threeSum(nums: number[]): number[][] {
    let left = 0
    let right = 1
    const numMap = new Map()
    for (let i = 0; i < nums.length; i++){
        numMap.set(nums[i], i)
    }
    const results = new Map()
 
    while (left < nums.length - 1){
 
        if (right >= nums.length){
            left++
            right = left + 1
            continue
        }
 
        const negativeSum = (nums[left] + nums[right]) * -1
        if (numMap.has(negativeSum)){
            const sumIndex = numMap.get(negativeSum)!
            if (sumIndex !== left && sumIndex !== right){
                const arr = [negativeSum, nums[left], nums[right]]
                results.set(arr.sort((a, b)=>a-b).join('-'), arr)
            } 
        }
 
        right++
    }
 
    return [...results].map(_=>_[1])
};

Claude didn’t think it was possible! Or at least never really suggested it the way I was doing it, no matter how I prodded her/him/it/our sacred AI lord and savior who art in heaven.

It did fail this one test case out of 313 test cases:

[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

Hmm. Wonder why that is. Yeah Claude really doesn’t like that I’m using this map, but I feel like a map makes so much sense here and is actually really cool.

But supposedly it’s not very efficient. Here’s a leetcode solution someone provided:

function threeSum(nums: number[]): number[][] {
  nums = nums.sort((a, b) => a - b)
  const ans: number[][] = []
  for (let left = 0; left < nums.length - 2; left++) {
    if (nums[left] > 0) break
    if (left > 0 && nums[left] === nums[left - 1]) continue

    let middle = left + 1
    let right = nums.length - 1
    while (middle < right) {
      const sum = nums[left] + nums[middle] + nums[right]
      if (sum === 0) {
        ans.push([nums[left], nums[middle], nums[right]])
        while (middle < right && nums[middle] === nums[middle + 1]) middle++
        while (middle < right && nums[right] === nums[right - 1]) right--
        middle++
        right--
      } else if (sum > 0) {
        right--
      } else {
        middle++
      }
    }
  }
  return ans
}

So verbose! I don’t understand if (left > 0 && nums[left] === nums[left - 1]) continue because i is supposed to != k, etc., as in the indexes providing values for each triplet are supposed to be unique, yet this seems to enforce uniqueness of the values which I’m 95% sure is not the goal here. I have to get some rest though, i’ll return to this.

Revisit 1

Wow, looking at this with a slightly more open mind, I totally missed the point of the sorting. Since the outcome has to be at least 0, we want to sort so that we can make sure as we iterate through, our left pointer is 0 or left, otherwise there’s no way we’re going to be able to reach 0.

This might seem sort of obvious, but looking at the solution for this algo, I think I unlocked a less murky way to think about loops.

This whole time, although I was able to follow code through a loop, I think that somehow it felt a little awkward, but this way of thinking fixes that;

A loop has a gate, which is the initialization of the loop. When the execution passes that line, it’s passing through that gate, like a sheep easily hopping a fence, or perhaps a droplet of water falling through the open top of a cup.

When that loop starts, if the loop has been initialized correctly, the only thing it has ‘added’ to the code is the following:

let i = 0

We have a variable set to 0. That’s it. For all other intents and purposes, until we get to the end of the loop, it’s as if we haven’t even interrupted our code at all.

I find that this way of thinking, the open-topped-cup, it helps me feel comfortable about reasoning with the first iteration of the loop, the starting condition, as a continuous part of the rest of the execution.

Before, I believe I sort of separated it in my mind, as a different scope, a different context, like some sort of module we drop it. And it is all of those things, but that type of separation made me think more along the lines of “Okay and now we enter the for loop, and in the for loop this is what’s happening…”

But there’s no “entering” really, it’s continuous space. Just a new variable, i = 0, or whatever we are looking for.

------- ------- ^ | | | ---v

Okay now looks look at the solution.

function threeSum(nums: number[]): number[][] {
  nums = nums.sort((a, b) => a - b)
  const ans: number[][] = []
  for (let left = 0; left < nums.length - 2; left++) {
    if (nums[left] > 0) break
    if (left > 0 && nums[left] === nums[left - 1]) continue
 
    let middle = left + 1
    let right = nums.length - 1
    while (middle < right) {
      const sum = nums[left] + nums[middle] + nums[right]
      if (sum === 0) {
        ans.push([nums[left], nums[middle], nums[right]])
        while (middle < right && nums[middle] === nums[middle + 1]) middle++
        while (middle < right && nums[right] === nums[right - 1]) right--
        middle++
        right--
      } else if (sum > 0) {
        right--
      } else {
        middle++
      }
    }
  }
  return ans
}

This is actually so dope. Let’s go through it line by line.

function threeSum(nums: number[]): number[][] {
 
  nums = nums.sort((a, b) => a - b) // sort it - this let's us compare stuff later, you'll see
  const ans: number[][] = []
  for (let left = 0; left < nums.length - 2; left++) {
  // left < nums.length would keep us from going past the last index
  // but we're going to define middle and right, so we actually need room
  // for TWO MORE BEFORE we hit the last index, hence -2
    if (nums[left] > 0) break
    // If left is MORE than 0, shit!
    // Right and middle could be anything, they ain't gonna add to 0
    // We can quit the whole operation here, there's nothing left to do!
    // But not that if left is 0, we hold out hope - 
    // Maybe, just maybe all the rest of the values are 0 too!
    // That's our only hope
    if (left > 0 && nums[left] === nums[left - 1]) continue
	// Ah yes, we have to check one more thing -
	// That we aren't checking a `left` value we've already checked.
	// Of course, my thinking is that we wouldn't have to do this if we
	// just switched it to a set to begin with - 
	// In my head, in an ETL way, if that's the definition of the data we want
	// We might as well just transform it to keep things simple BEFORE
	// We go into this multi-conditional loop and keep things more readable
	// But I'd guess this is cheaper, and it's only a line, so it makes sense.
    let middle = left + 1
    // Now we calculate middle! Middle starts as a reference to left
    // Put another way, the first possible value that ISN'T our current left.
    // So I guess in this way, we sort of have two left pointers
    // But then we'd need to iterations, right? Yeah. One sec.
    let right = nums.length - 1
    // And right always starts as a reference to the last possible value.
    while (middle < right) {
    // Ah there's our second iterator! So left is the parent iterator
    // And within it, we have another level of iteration
    // for every time our left iterates rightwards, we
    // also tweak our other pointers through another level of iteration
      const sum = nums[left] + nums[middle] + nums[right]
      // We need this sum for a few reasons
      if (sum === 0) {
	    // The first reason is the success case
        ans.push([nums[left], nums[middle], nums[right]])
        // If we have success, we save it
        while (middle < right && nums[middle] === nums[middle + 1]) middle++
        // Hot damn! What is this?? This is the cutest little powerhouse of a while loop I've ever seen
        // This thing is saying, as long as middle is less than right
        // i.e. they haven't converged
        // And as long as the MIDDLE isn't a duplicate
        while (middle < right && nums[right] === nums[right - 1]) right--
        middle++
        right--
      } else if (sum > 0) {
        right--
      } else {
        middle++
      }
    }
  }
  return ans
}

I wonder why we would check duplicates to middle with a +1 index check, yet for left we’re doing a -1 index check. Maybe it doesn’t matter?

No, it’s because one is a check to make sure something ISN’T the case, and the other is checking to make sure something IS the case.

For the middle check I understand. But for the left check, I would think these two lines would play the same:

if (left > 0 && nums[left] === nums[left - 1]) continue
if (left > 0 && nums[left] === nums[left + 1]) continue

In the first one, we’d skip any duplicates of left that occurred after the first instance of that value.

In the second one, we’d skip any duplicates that happened before the last instance of that value.

You know, I think I have a little misunderstanding here. The INDEXES must all be different, but the values can be the same. Like 0, 0, 0 is a valid answer. If this isn’t abundantly clear in the problem’s language, it is clear in the problem sets.

However, the only time all three values COULD be the same WOULD be 0, 0, 0.

However #2, two out of three of the values could be the same. -6, -6, 12, or the reverse -6, 3, 3.