2190. Most Frequent Number Following Key In an Array
Problem Description
You have an integer array nums
(0-indexed) and an integer key
that appears in the array.
Your task is to find which number appears most frequently immediately after key
in the array.
Specifically, for each unique integer target
in nums
, count how many times target
appears right after key
. This means counting the number of valid indices i
where:
i
is between0
andnums.length - 2
(inclusive)nums[i] == key
nums[i + 1] == target
Return the target
value that has the maximum count. The problem guarantees that there will be exactly one target with the maximum count (no ties).
For example, if nums = [1, 100, 200, 1, 100]
and key = 1
, you would check what comes after each occurrence of 1
:
- At index 0:
1
is followed by100
- At index 3:
1
is followed by100
So 100
appears 2 times after key = 1
, making it the answer.
Intuition
The problem asks us to find the most frequent number that appears immediately after a specific key
value. This is essentially a counting problem where we need to track consecutive pairs.
The key insight is that we need to examine every consecutive pair (nums[i], nums[i+1])
in the array. Whenever the first element of a pair equals key
, we should count the second element as a potential answer.
To solve this efficiently, we can use a hash table (or Counter in Python) to keep track of how many times each number appears after key
. As we traverse the array:
- Check each consecutive pair
- When we find
nums[i] == key
, increment the count fornums[i+1]
- Keep track of the maximum count seen so far and which number has that count
This approach works because:
- We only need one pass through the array
- The hash table allows us to count occurrences of each target in O(1) time
- By maintaining the maximum count during traversal, we avoid needing a second pass to find the answer
The pairwise
function in Python makes this even cleaner by automatically giving us consecutive pairs (a, b)
from the array, where we can simply check if a == key
and then count b
.
Solution Approach
The solution uses a hash table to count occurrences and a single traversal to find the answer.
Data Structures Used:
Counter
(hash table): To store the count of each target that appears afterkey
- Two variables:
mx
to track the maximum count, andans
to store the target with maximum count
Implementation Steps:
-
Initialize the data structures:
- Create a
Counter
objectcnt
to store frequency counts - Set
ans = 0
(to store the final answer) andmx = 0
(to track maximum frequency)
- Create a
-
Traverse consecutive pairs:
- Use
pairwise(nums)
to iterate through all consecutive pairs(a, b)
in the array - This gives us pairs like
(nums[0], nums[1])
,(nums[1], nums[2])
, etc.
- Use
-
Count targets after key:
- For each pair
(a, b)
:- If
a == key
, thenb
is a target that followskey
- Increment the count:
cnt[b] += 1
- If
- For each pair
-
Update maximum on the fly:
- After incrementing
cnt[b]
, check if this new count exceedsmx
- If
mx < cnt[b]
:- Update
mx = cnt[b]
(new maximum count) - Update
ans = b
(the target with this maximum count)
- Update
- After incrementing
-
Return the result:
- After traversing all pairs,
ans
contains the target with the maximum count
- After traversing all pairs,
Time Complexity: O(n) where n is the length of nums
, as we traverse the array once.
Space Complexity: O(k) where k is the number of unique targets that appear after key
, for storing the counts in the hash table.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [2, 2, 2, 2, 3]
and key = 2
.
Step 1: Initialize data structures
cnt = {}
(empty counter)ans = 0
(will store our answer)mx = 0
(tracks maximum frequency)
Step 2: Process consecutive pairs
We'll examine each consecutive pair (a, b)
:
Pair 1: (2, 2) at indices (0, 1)
a = 2
equalskey = 2
✓- So
b = 2
is a target that follows key - Update:
cnt[2] = 1
- Check maximum:
cnt[2] = 1 > mx = 0
✓ - Update:
mx = 1
,ans = 2
Pair 2: (2, 2) at indices (1, 2)
a = 2
equalskey = 2
✓- So
b = 2
is a target that follows key - Update:
cnt[2] = 2
- Check maximum:
cnt[2] = 2 > mx = 1
✓ - Update:
mx = 2
,ans = 2
Pair 3: (2, 2) at indices (2, 3)
a = 2
equalskey = 2
✓- So
b = 2
is a target that follows key - Update:
cnt[2] = 3
- Check maximum:
cnt[2] = 3 > mx = 2
✓ - Update:
mx = 3
,ans = 2
Pair 4: (2, 3) at indices (3, 4)
a = 2
equalskey = 2
✓- So
b = 3
is a target that follows key - Update:
cnt[3] = 1
- Check maximum:
cnt[3] = 1 > mx = 3
? ✗ - No update needed (3 still has the maximum count)
Step 3: Return the result
- Final counter:
cnt = {2: 3, 3: 1}
- The number
2
appears 3 times afterkey = 2
- The number
3
appears 1 time afterkey = 2
- Return
ans = 2
The answer is 2
because it appears most frequently (3 times) immediately after the key value 2
.
Solution Implementation
1class Solution:
2 def mostFrequent(self, nums: List[int], key: int) -> int:
3 # Dictionary to count occurrences of elements that follow the key
4 count_map = {}
5
6 # Variables to track the result and maximum frequency
7 result = 0
8 max_frequency = 0
9
10 # Iterate through consecutive pairs in the array
11 for i in range(len(nums) - 1):
12 current_element = nums[i]
13 next_element = nums[i + 1]
14
15 # Check if current element matches the key
16 if current_element == key:
17 # Increment count for the element following the key
18 if next_element not in count_map:
19 count_map[next_element] = 0
20 count_map[next_element] += 1
21
22 # Update result if we found a more frequent target
23 if max_frequency < count_map[next_element]:
24 max_frequency = count_map[next_element]
25 result = next_element
26
27 return result
28
1class Solution {
2 public int mostFrequent(int[] nums, int key) {
3 // Array to store frequency count of target values (range: 1-1000)
4 int[] frequencyCount = new int[1001];
5
6 // Variable to store the answer (most frequent target)
7 int mostFrequentTarget = 0;
8
9 // Variable to track the maximum frequency encountered
10 int maxFrequency = 0;
11
12 // Iterate through the array, checking each pair of adjacent elements
13 for (int i = 0; i < nums.length - 1; i++) {
14 // Check if current element matches the key
15 if (nums[i] == key) {
16 // Increment frequency count for the target (next element after key)
17 int targetValue = nums[i + 1];
18 frequencyCount[targetValue]++;
19
20 // Update the most frequent target if current frequency is higher
21 if (frequencyCount[targetValue] > maxFrequency) {
22 maxFrequency = frequencyCount[targetValue];
23 mostFrequentTarget = targetValue;
24 }
25 }
26 }
27
28 // Return the most frequent target value
29 return mostFrequentTarget;
30 }
31}
32
1class Solution {
2public:
3 int mostFrequent(vector<int>& nums, int key) {
4 // Array to count occurrences of each target value (constraint: values are 1-1000)
5 int count[1001]{};
6
7 // Track the result (most frequent target) and its maximum frequency
8 int result = 0;
9 int maxFrequency = 0;
10
11 // Iterate through the array, stopping before the last element
12 // since we need to check nums[i+1]
13 for (int i = 0; i < nums.size() - 1; ++i) {
14 // Check if current element matches the key
15 if (nums[i] == key) {
16 // Increment count for the target (next element after key)
17 int targetValue = nums[i + 1];
18 count[targetValue]++;
19
20 // Update result if this target appears more frequently
21 if (count[targetValue] > maxFrequency) {
22 maxFrequency = count[targetValue];
23 result = targetValue;
24 }
25 }
26 }
27
28 return result;
29 }
30};
31
1/**
2 * Finds the most frequent element that appears immediately after the key element in the array
3 * @param nums - The input array of numbers
4 * @param key - The key element to search for
5 * @returns The most frequent element that appears after the key element
6 */
7function mostFrequent(nums: number[], key: number): number {
8 // Create a frequency counter array with size based on the maximum value in nums
9 // This array tracks how many times each number appears after the key
10 const frequencyCounter: number[] = Array(Math.max(...nums) + 1).fill(0);
11
12 // Initialize variables to track the answer and maximum frequency
13 let mostFrequentTarget: number = 0; // The element that appears most frequently after key
14 let maxFrequency: number = 0; // The maximum frequency encountered
15
16 // Iterate through the array, stopping one element before the end
17 // since we need to check the next element
18 for (let i = 0; i < nums.length - 1; i++) {
19 // Check if current element matches the key
20 if (nums[i] === key) {
21 // Get the target element (the element immediately after the key)
22 const target: number = nums[i + 1];
23
24 // Increment the frequency count for the target element
25 frequencyCounter[target]++;
26
27 // Update the result if this target has a higher frequency than previous maximum
28 if (frequencyCounter[target] > maxFrequency) {
29 maxFrequency = frequencyCounter[target];
30 mostFrequentTarget = target;
31 }
32 }
33 }
34
35 return mostFrequentTarget;
36}
37
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the array nums
. The algorithm iterates through the array once using pairwise(nums)
, which generates n-1
pairs. For each pair, it performs constant-time operations: checking if a == key
, updating the counter, and comparing/updating the maximum frequency.
The space complexity is O(M)
, where M
represents the number of distinct elements that appear immediately after the key
in the array. In the worst case, this could be all unique values that follow the key
, which is bounded by the maximum value of elements in nums
if we consider the counter stores at most M
distinct integers. The Counter
object stores the frequency of each target element that appears after key
, and the additional variables (ans
, mx
) use O(1)
space.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Off-by-One Error in Loop Range
A common mistake is iterating through the entire array without considering that we need to check pairs. If you iterate up to len(nums)
instead of len(nums) - 1
, you'll get an index out of bounds error when accessing nums[i + 1]
.
Incorrect:
for i in range(len(nums)): # Goes up to len(nums) - 1
if nums[i] == key:
target = nums[i + 1] # IndexError when i = len(nums) - 1
Correct:
for i in range(len(nums) - 1): # Stops at len(nums) - 2
if nums[i] == key:
target = nums[i + 1] # Safe access
2. Not Handling Empty or Single-Element Arrays
The code assumes there are at least two elements to form a pair. Edge cases with empty arrays or arrays with only one element could cause issues.
Solution: Add a guard clause at the beginning:
if len(nums) < 2:
return 0 # or handle according to problem constraints
3. Incorrect Maximum Tracking
Some might try to find all counts first, then search for the maximum in a separate pass. This works but is less efficient and more error-prone.
Less Efficient Approach:
# First pass: count all
for i in range(len(nums) - 1):
if nums[i] == key:
count_map[nums[i + 1]] = count_map.get(nums[i + 1], 0) + 1
# Second pass: find maximum
result = 0
max_freq = 0
for target, count in count_map.items():
if count > max_freq:
max_freq = count
result = target
Better Approach (as shown in solution): Update the maximum during the counting process itself, eliminating the need for a second pass.
4. Using Wrong Comparison Operator
When updating the maximum, using <=
instead of <
could potentially return a different target if multiple targets have the same maximum count (though the problem guarantees uniqueness).
Potentially Problematic:
if max_frequency <= count_map[next_element]: # Uses <= max_frequency = count_map[next_element] result = next_element
Correct:
if max_frequency < count_map[next_element]: # Uses < max_frequency = count_map[next_element] result = next_element
5. Forgetting to Initialize Dictionary Values
When using a regular dictionary instead of defaultdict
or Counter
, forgetting to initialize new keys leads to KeyError.
Incorrect:
count_map[next_element] += 1 # KeyError if next_element not in count_map
Correct:
if next_element not in count_map: count_map[next_element] = 0 count_map[next_element] += 1
Or use defaultdict
:
from collections import defaultdict
count_map = defaultdict(int)
count_map[next_element] += 1 # Automatically initializes to 0
You are given an array of intervals where intervals[i] = [start_i, end_i]
represent the start and end of the ith
interval. You need to merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!