class Solution:
def numberOfArithmeticSlices(self, nums):
n = len(nums)
if n < 3:
return 0
count = 0
curr = 0
for i in range(2, n):
if nums[i] - nums[i-1] == nums[i-1] - nums[i-2]:
curr += 1
count += curr
else:
curr = 0
return count
class Solution {
public:
int numberOfArithmeticSlices(vector<int>& nums) {
int n = nums.size();
if (n < 3) return 0;
int count = 0, curr = 0;
for (int i = 2; i < n; ++i) {
if (nums[i] - nums[i-1] == nums[i-1] - nums[i-2]) {
curr += 1;
count += curr;
} else {
curr = 0;
}
}
return count;
}
};
class Solution {
public int numberOfArithmeticSlices(int[] nums) {
int n = nums.length;
if (n < 3) return 0;
int count = 0, curr = 0;
for (int i = 2; i < n; i++) {
if (nums[i] - nums[i-1] == nums[i-1] - nums[i-2]) {
curr++;
count += curr;
} else {
curr = 0;
}
}
return count;
}
}
var numberOfArithmeticSlices = function(nums) {
let n = nums.length;
if (n < 3) return 0;
let count = 0, curr = 0;
for (let i = 2; i < n; i++) {
if (nums[i] - nums[i-1] === nums[i-1] - nums[i-2]) {
curr++;
count += curr;
} else {
curr = 0;
}
}
return count;
};
Given an array of integers nums
, your task is to return the number of arithmetic slices in nums
.
An arithmetic slice is a subarray with at least three elements where the difference between any two consecutive elements is the same. In other words, for any subarray nums[i], nums[i+1], ..., nums[j]
(where j - i + 1 >= 3
), the difference nums[k+1] - nums[k]
must be constant for all valid k
.
nums
can be used in multiple slices, but each slice is counted only once.nums
can contain positive, negative, or zero values.
To solve this problem, we first need to understand what constitutes an arithmetic slice. The key observation is that any subarray of length 3 or more, where the difference between consecutive elements is constant, is a valid slice.
A brute-force approach would be to check every possible subarray of length at least 3, and for each, verify if it is arithmetic. However, this approach is inefficient for large arrays.
Instead, we look for patterns: if three consecutive elements form an arithmetic sequence, so do the last three of any longer sequence with the same difference. This means we can build upon previously found arithmetic slices, counting how many new ones are formed as we extend the sequence.
This leads to an optimized approach where, as we scan through the array, we keep track of how many arithmetic slices end at each position, and accumulate the total.
count
for the total number of arithmetic slices, and curr
for the number of arithmetic slices ending at the current index.
i
, check if nums[i] - nums[i-1]
equals nums[i-1] - nums[i-2]
. If true, it means the current three elements form an arithmetic sequence.
curr
(since any previous slice ending at i-1
can be extended by nums[i]
), and add curr
to count
.
curr
to 0.
count
contains the total number of arithmetic slices.
This approach is efficient because it avoids redundant checks and leverages the structure of arithmetic sequences to build longer slices from shorter ones.
Consider the input nums = [1, 2, 3, 4]
.
Let's trace the iterations:
i = 2
: nums[2] - nums[1] = 1
, nums[1] - nums[0] = 1
(equal, so arithmetic). curr = 1
, count = 1
(slice: [1,2,3])i = 3
: nums[3] - nums[2] = 1
, nums[2] - nums[1] = 1
(equal, so arithmetic). curr = 2
, count = 3
(slices: [2,3,4] and [1,2,3,4])The arithmetic slices are: [1,2,3], [2,3,4], and [1,2,3,4] (which contains both previous slices). Thus, the answer is 3.
The key insight is that arithmetic slices can be counted efficiently by building on previously found slices as we iterate through the array. By keeping track of how many slices end at each position and extending them when possible, we achieve a linear-time solution. This method is both elegant and practical, making it suitable for large input sizes.