2367. Number of Arithmetic Triplets(en)

Introduction

You’re given a strictly increasing array of integers nums, and you need to count how many triplets satisfy the following conditions. Looking at the constraints, 3 <= nums.length <= 200, I immediately thought, “Alright, brute force should work just fine.” And, sure enough, the hint basically winks at you and says, “Brute force, huh? Maybe give it a shot?” Yeah, I got this.

1
2
i < j < k,
nums[j] - nums[i] == diff and nums[k] - nums[j] == diff

So, with a slight blush of overconfidence, I banged out the code below.

LeetCode Submission

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func arithmeticTriplets(nums []int, diff int) int {
    ans := 0
    for i := 0; i < len(nums); i++ {
        for j := i + 1; j < len(nums); j++ {
            for k := j + 1; k < len(nums); k++ {
                if nums[j] - nums[i] == diff && nums[k] - nums[j] == diff {
                    ans++
                }
            }
        }
    }
    return ans
}

No explanation needed—none whatsoever. It’s just a straight-up brute force, checking every possible triplet. Done. Let’s move on.

Round Two

After a bit of thinking, I landed on a better approach. It’s not like I’m jumping for joy—it beats 100% of submissions, but it doesn’t feel elegant. Probably because I didn’t fully validate the algorithm before coding. My first instinct was to aim for O(n), but I settled for O(n²) to get something working.

The idea? Track the previous state while iterating. For example, with the input below, nums[1]: 1 pairs with nums[2]: 4 to satisfy diff. You store that 4 as the previous value, then look for the next index that satisfies diff relative to 4. In this case, it’s nums[4]: 7. Since the array is guaranteed to be strictly increasing, you don’t need to keep searching—any further values will have a larger difference than diff. Boom, double loop does the trick.

1
Input: nums = [0,1,4,6,7,10], diff = 3

LeetCode Submission

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func arithmeticTriplets(nums []int, diff int) int {
    ans := 0
    for i := 0; i < len(nums); i++ {
        prev := nums[i]
        for j := i + 1; j < len(nums); j++ {
            if nums[j] - prev == diff {
                if prev != nums[i] {
                    ans++
                    break
                }
                prev = nums[j]
            }
        }
    }
    return ans
}

The Elegant Solution

Hold up—whoa. Check out this solution. The code speaks for itself. It’s clean, simple, and probably why this problem is tagged as “Easy.” Sure, brute force works, but this? This is poetry. No need to even think about time complexity in the brute force case, but this approach makes you appreciate the problem’s simplicity.

It’s a single loop. The logic? Dead simple. If you find a value that’s at least diff * 2, check if n - diff and n - diff * 2 exist earlier in the array. If they do, increment the count. That’s it.

LeetCode Submission

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
func arithmeticTriplets(nums []int, diff int) int {
    cnt, ans := make([]int, 201), 0
    for _, n := range nums {
        if n >= 2*diff {
            ans += cnt[n-diff] & cnt[n-diff*2]
        }
        cnt[n] = 1
    }
    return ans
}

In production code, I’d avoid declaring and initializing multiple variables in one line like this—it’s a bit too clever for maintainability. Competitive programming loves this kind of concise flair, but in the real world, you write for the poor soul who has to maintain your code. So, you might see something like this instead:

1
2
3
4
5
6
7
var (
    cnt []int
    ans int
)

cnt = make([]int, 201)
ans = 0

Looks verbose, right? But separating “here’s the variable” from “here’s its value” makes it easier to grok for whoever’s debugging at 2 a.m. In this case, though, it’s not the best example—let’s just say I’ll save that rant for another post.

Hugo で構築されています。
テーマ StackJimmy によって設計されています。