🧠
Dynamic Programming with Hash Maps (Tracking Differences)
💡 This approach introduces memoization by storing the length of arithmetic subsequences ending at each index with a given difference, avoiding repeated scanning.
Intuition
For each element, look back at previous elements and update the length of subsequences with the difference between them. Use a hash map to track lengths by difference.
Algorithm
- Initialize an array of hash maps dp, where dp[i] maps difference to length of arithmetic subsequence ending at i.
- Iterate over each pair (j, i) with j < i, compute diff = nums[i] - nums[j].
- Update dp[i][diff] = dp[j].get(diff, 1) + 1, extending the subsequence ending at j.
- Track the maximum length found during updates.
💡 This approach avoids scanning ahead by building solutions bottom-up and remembering lengths for each difference.
def longestArithSeqLength(nums):
n = len(nums)
dp = [dict() for _ in range(n)]
max_len = 2 if n >= 2 else n
for i in range(n):
for j in range(i):
diff = nums[i] - nums[j]
length = dp[j].get(diff, 1) + 1
dp[i][diff] = max(dp[i].get(diff, 0), length)
max_len = max(max_len, dp[i][diff])
return max_len
# Example usage
if __name__ == '__main__':
print(longestArithSeqLength([3,6,9,12])) # Output: 4
Line Notes
dp = [dict() for _ in range(n)]Create a list of dictionaries to store difference-length mappings per index
max_len = 2 if n >= 2 else nInitialize max length with minimum valid subsequence length
for i in range(n)Iterate over each element as the subsequence end
for j in range(i)Look back at all previous elements to find differences
diff = nums[i] - nums[j]Calculate difference between current and previous element
length = dp[j].get(diff, 1) + 1Extend subsequence length if difference seen before, else start new length 2
dp[i][diff] = max(dp[i].get(diff, 0), length)Update dp for current index and difference with max length
max_len = max(max_len, dp[i][diff])Track global maximum length
return max_lenReturn the longest arithmetic subsequence length found
import java.util.*;
public class Solution {
public static int longestArithSeqLength(int[] nums) {
int n = nums.length;
Map<Integer, Integer>[] dp = new HashMap[n];
for (int i = 0; i < n; i++) dp[i] = new HashMap<>();
int maxLen = n >= 2 ? 2 : n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
int diff = nums[i] - nums[j];
int length = dp[j].getOrDefault(diff, 1) + 1;
dp[i].put(diff, Math.max(dp[i].getOrDefault(diff, 0), length));
maxLen = Math.max(maxLen, dp[i].get(diff));
}
}
return maxLen;
}
public static void main(String[] args) {
System.out.println(longestArithSeqLength(new int[]{3,6,9,12})); // Output: 4
}
}
Line Notes
Map<Integer, Integer>[] dp = new HashMap[n];Array of hash maps to store difference-length pairs per index
for (int i = 0; i < n; i++) dp[i] = new HashMap<>();Initialize each map
int maxLen = n >= 2 ? 2 : n;Initialize max length with minimum valid subsequence length
for (int i = 0; i < n; i++)Iterate over each element as subsequence end
for (int j = 0; j < i; j++)Look back at previous elements
int diff = nums[i] - nums[j];Calculate difference
int length = dp[j].getOrDefault(diff, 1) + 1;Extend subsequence length or start new
dp[i].put(diff, Math.max(dp[i].getOrDefault(diff, 0), length));Update dp with max length for difference
maxLen = Math.max(maxLen, dp[i].get(diff));Update global max length
return maxLen;Return final answer
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
int longestArithSeqLength(vector<int>& nums) {
int n = nums.size();
vector<unordered_map<int,int>> dp(n);
int maxLen = n >= 2 ? 2 : n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
int diff = nums[i] - nums[j];
int length = dp[j].count(diff) ? dp[j][diff] + 1 : 2;
dp[i][diff] = max(dp[i][diff], length);
maxLen = max(maxLen, dp[i][diff]);
}
}
return maxLen;
}
int main() {
vector<int> nums = {3,6,9,12};
cout << longestArithSeqLength(nums) << endl; // Output: 4
return 0;
}
Line Notes
vector<unordered_map<int,int>> dp(n);Vector of hash maps to store difference-length pairs per index
int maxLen = n >= 2 ? 2 : n;Initialize max length with minimum valid subsequence length
for (int i = 0; i < n; i++)Iterate over each element as subsequence end
for (int j = 0; j < i; j++)Look back at previous elements
int diff = nums[i] - nums[j];Calculate difference
int length = dp[j].count(diff) ? dp[j][diff] + 1 : 2;Extend subsequence length or start new length 2
dp[i][diff] = max(dp[i][diff], length);Update dp with max length for difference
maxLen = max(maxLen, dp[i][diff]);Update global max length
return maxLen;Return final answer
function longestArithSeqLength(nums) {
const n = nums.length;
const dp = Array.from({length: n}, () => new Map());
let maxLen = n >= 2 ? 2 : n;
for (let i = 0; i < n; i++) {
for (let j = 0; j < i; j++) {
const diff = nums[i] - nums[j];
const length = dp[j].has(diff) ? dp[j].get(diff) + 1 : 2;
dp[i].set(diff, Math.max(dp[i].get(diff) || 0, length));
maxLen = Math.max(maxLen, dp[i].get(diff));
}
}
return maxLen;
}
// Example usage
console.log(longestArithSeqLength([3,6,9,12])); // Output: 4
Line Notes
const dp = Array.from({length: n}, () => new Map());Create array of maps to track difference-length pairs per index
let maxLen = n >= 2 ? 2 : n;Initialize max length with minimum valid subsequence length
for (let i = 0; i < n; i++)Iterate over each element as subsequence end
for (let j = 0; j < i; j++)Look back at previous elements
const diff = nums[i] - nums[j];Calculate difference
const length = dp[j].has(diff) ? dp[j].get(diff) + 1 : 2;Extend subsequence length or start new length 2
dp[i].set(diff, Math.max(dp[i].get(diff) || 0, length));Update dp with max length for difference
maxLen = Math.max(maxLen, dp[i].get(diff));Update global max length
return maxLen;Return final answer
Two nested loops for pairs, and each index stores a map of differences which can be up to O(n) in worst case.
💡 For n=1000, about 1 million operations, which is feasible in interviews and production.
Interview Verdict: Accepted
This approach is efficient enough for large inputs and is the standard solution for this problem.