446. Arithmetic Slices II - Subsequence
Given an integer array nums, return the number of all the arithmetic subsequences of nums.
A sequence of numbers is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same.
- For example, [1, 3, 5, 7, 9], [7, 7, 7, 7], and [3, -1, -5, -9] are arithmetic sequences.
- For example, [1, 1, 2, 5, 7] is not an arithmetic sequence.
A subsequence of an array is a sequence that can be formed by removing some elements (possibly none) of the array.
- For example, [2,5,10] is a subsequence of [1,2,1,2,4,1,5,10].
The test cases are generated so that the answer fits in 32-bit integer.
Example 1:
Input: nums = [2,4,6,8,10]
Output: 7
Explanation: All arithmetic subsequence slices are:
[2,4,6]
[4,6,8]
[6,8,10]
[2,4,6,8]
[4,6,8,10]
[2,4,6,8,10]
[2,6,10]
Example 2:
Input: nums = [7,7,7,7,7]
Output: 16
Explanation: Any subsequence of this array is arithmetic.
Constraints:
- 1 <= nums.length <= 1000
- − 2 31 < = n u m s [ i ] < = 2 31 − 1 -2^{31} <= nums[i] <= 2^{31} - 1 −231<=nums[i]<=231−1
From: LeetCode
Link: 446. Arithmetic Slices II - Subsequence
Solution:
Ideas:
1. HashMap Structure:
- We use HashMap to store the number of subsequences ending at each index with a specific difference.
- This avoids creating a massive 2D array, which could be memory-intensive.
2. Updating Counts:
- For each pair (i, j), calculate the difference diff = nums[i] - nums[j].
- We look up the count of sequences with this difference ending at j (dp[j][diff]), then add this count to result.
- We also update dp[i][diff] by adding count + 1, where 1 represents a new sequence [nums[j], nums[i]].
3. Final Result:
- Sum all valid sequences of length ≥ 3 found in each step.
Code:
#define HASH_SIZE 1000
typedef struct HashNode {
long key;
int value;
struct HashNode *next;
} HashNode;
typedef struct {
HashNode *buckets[HASH_SIZE];
} HashMap;
// Hash function
int hash(long key) {
return (int)((key % HASH_SIZE + HASH_SIZE) % HASH_SIZE);
}
// Create a new hashmap
HashMap* createHashMap() {
HashMap* map = (HashMap*)malloc(sizeof(HashMap));
memset(map->buckets, 0, sizeof(map->buckets));
return map;
}
// Insert or update key-value in hashmap
void put(HashMap* map, long key, int value) {
int index = hash(key);
HashNode *node = map->buckets[index];
while (node) {
if (node->key == key) {
node->value += value;
return;
}
node = node->next;
}
// Insert new node if key not found
HashNode *newNode = (HashNode*)malloc(sizeof(HashNode));
newNode->key = key;
newNode->value = value;
newNode->next = map->buckets[index];
map->buckets[index] = newNode;
}
// Get value from hashmap
int get(HashMap* map, long key) {
int index = hash(key);
HashNode *node = map->buckets[index];
while (node) {
if (node->key == key) return node->value;
node = node->next;
}
return 0;
}
// Free hashmap
void freeHashMap(HashMap* map) {
for (int i = 0; i < HASH_SIZE; i++) {
HashNode *node = map->buckets[i];
while (node) {
HashNode *temp = node;
node = node->next;
free(temp);
}
}
free(map);
}
int numberOfArithmeticSlices(int* nums, int numsSize) {
HashMap **dp = (HashMap**)malloc(numsSize * sizeof(HashMap*));
for (int i = 0; i < numsSize; i++) {
dp[i] = createHashMap();
}
int result = 0;
for (int i = 0; i < numsSize; i++) {
for (int j = 0; j < i; j++) {
long diff = (long)nums[i] - (long)nums[j];
int count = get(dp[j], diff);
result += count;
put(dp[i], diff, count + 1);
}
}
for (int i = 0; i < numsSize; i++) {
freeHashMap(dp[i]);
}
free(dp);
return result;
}