Problem Statement

Arithmetic Slices

An array is called arithmetic when it has at least three numbers and the gap between each pair of neighbors stays the same. For example, [2,4,6,8] is arithmetic because you add 2 every time. The job here is to count how many arithmetic subarrays live inside the array. A subarray is a slice of numbers that sit next to each other, with nothing skipped. So from [1,3,5,7,9] you can pull [1,3,5], [3,5,7], [5,7,9], [1,3,5,7], [3,5,7,9], and [1,3,5,7,9], which is 6 of them. The tool we lean on is dynamic programming, which is a fancy name for a simple habit, solve a small piece, remember the answer, and reuse it to solve the next piece. That fits because the count of slices ending at one spot is built directly from the count of slices ending at the spot just before it.

mediumDynamic ProgrammingDynamic ProgrammingTime: O(n) · Space: O(1)

Signals to notice

count subarrays forming arithmetic sequencecommon difference between consecutive elementsextend or break

Brute force first

Check every subarray for arithmetic property. Each subarray is independently validated. That instinct is useful because it follows the prompt literally, but it usually keeps revisiting work the problem is begging you to organize.

The key insight

DP: dp[i] = number of arithmetic slices ending at index i. If nums[i] - nums[i-1] == nums[i-1] - nums[i-2], then dp[i] = dp[i-1] + 1 (extend the sequence). Otherwise dp[i] = 0. Sum all dp values. Instead of recomputing the world every time, you preserve just enough context to let the next decision become obvious.

Trace it on nums=[1,2,3,8,9,10] (expected 2)

init: dp=0, total=0
i=2: diff 3-2==2-1 (1==1) extend -> dp=1, total=1
i=3: diff 8-3 vs 3-2 (5!=1) break -> dp=0, total=1
i=4: diff 9-8 vs 8-3 (1!=5) break -> dp=0, total=1
i=5: diff 10-9==9-8 (1==1) extend -> dp=1, total=2
return total=2

What must stay true

Each new element either extends the current arithmetic run (same common difference) or breaks it. When it extends, it adds dp[i-1] + 1 new slices — the previous count plus one new slice ending at i. As long as that statement keeps holding, you can trust the steps built on top of it.

Shape of the loop

dp = 0; total = 0
for i from 2 to n-1:
    if nums[i]-nums[i-1] == nums[i-1]-nums[i-2]:
        dp = dp + 1          # extend run: +1 new slice
        total = total + dp
    else: dp = 0             # run broke
return total

Pseudocode only — the full worked solution lives in the Solution tab.

Easy way to go wrong

Not understanding why dp[i] = dp[i-1] + 1 — extending a run of length k creates one additional slice of each length from 3 to k+1. The +1 accounts for the new minimum-length slice. When the code becomes mechanical before the idea is clear, small edge cases start breaking the whole story.

Dynamic Programming Pattern