Problem Statement
Given an array of n
integers, find the second most frequent element in it. If there are multiple elements that appear a maximum number of times, find the smallest of them. If second most frequent element does not exist return -1.
Examples
Example 1:
Input: arr = [1, 2, 2, 3, 3, 3]
Output: 2
Explanation: The number 2 appears the second most (2 times) and the number 3 appears the most (3 times).
Example 2:
Input: arr = [4, 4, 5, 5, 6, 7]
Output: 6
Explanation: Both 6 and 7 appear second most times (1 time), but 6 is smaller.
Example 3:
Input: arr = [10, 9, 7, 7]
Output: 9
Different Approaches
1️⃣ Brute Force Approach
Approach:
- Initialization:
n
: Size of the array.maxFreq
andsecMaxFreq
: Start at 0 (no frequency counted yet).maxEle
andsecEle
: Initially set to -1 (or any invalid value to indicate they haven’t been assigned).visited
: A Boolean vector of sizen
initialized tofalse
to mark whether an element's frequency has already been computed.
- Outer Loop (
for (int i = 0; i < n; i++)
):- Skip Already Visited:
Ifvisited[i]
istrue
, it means this element has already been counted, so we continue to the next iteration. - Counting Frequency:
Initializefreq
to 0 for the current elementnums[i]
. - Inner Loop (
for (int j = i; j < n; j++)
):
Comparenums[i]
with every element from indexi
onward:- If
nums[i]
equalsnums[j]
, incrementfreq
and markvisited[j]
astrue
to avoid recounting later.
- If
- Skip Already Visited:
- Updating Maximum and Second Maximum Frequencies:
- If
freq > maxFreq
:- Update
secMaxFreq
to the previousmaxFreq
andsecEle
to the previousmaxEle
. - Set
maxFreq
tofreq
andmaxEle
tonums[i]
.
- Update
- Else if
freq == maxFreq
:- Update
maxEle
with the smaller of the currentmaxEle
andnums[i]
(tie-breaker for the most frequent element).
- Update
- Else if
freq > secMaxFreq
:- Update
secMaxFreq
tofreq
andsecEle
tonums[i]
.
- Update
- Else if
freq == secMaxFreq
:- Update
secEle
with the smaller of the currentsecEle
andnums[i]
(tie-breaker for the second most frequent element).
- Update
- If
- Return Result:
- After all elements are processed, the function returns
secEle
, which holds the second highest occurring element.
- After all elements are processed, the function returns
Code:
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
// Function to get the second highest occurring element in array
int secondMostFrequentElement(vector<int> &nums) {
// Step 1: Get the size of the array
int n = nums.size();
// Step 2: Initialize frequency trackers
int maxFreq = 0; // Highest frequency so far
int secMaxFreq = 0; // Second highest frequency so far
// Step 3: Variables to store elements with highest and second highest frequencies
int maxEle = -1; // Element with highest frequency
int secEle = -1; // Element with second highest frequency
// Step 4: Boolean array to mark elements that have already been counted
vector<bool> visited(n, false);
// Step 5: Iterate through each element in the array
for (int i = 0; i < n; i++) {
// If this element was already counted in a previous pass, skip it
if (visited[i]) continue;
// Step 6: Count the frequency of nums[i]
int freq = 0; // Frequency counter for current element
// Step 7: Start from current index and count occurrences
for (int j = i; j < n; j++) {
if (nums[i] == nums[j]) {
freq++; // Count this occurrence
visited[j] = true; // Mark this index as visited
}
}
// Step 8: Update max and second max frequencies and their elements
// Case 1: New max frequency found
if (freq > maxFreq) {
secMaxFreq = maxFreq; // Update second max freq before overwriting maxFreq
maxFreq = freq; // Update max frequency
secEle = maxEle; // Update second most frequent element
maxEle = nums[i]; // Update most frequent element
}
// Case 2: Tie for max frequency — pick the smaller value
else if (freq == maxFreq) {
maxEle = min(maxEle, nums[i]);
}
// Case 3: New second max frequency
else if (freq > secMaxFreq) {
secMaxFreq = freq; // Update second max frequency
secEle = nums[i]; // Update second most frequent element
}
// Case 4: Tie for second max — pick the smaller value
else if (freq == secMaxFreq) {
secEle = min(secEle, nums[i]);
}
}
// Step 9: Return the second most frequent element
return secEle;
}
};
int main() {
// Step 10: Define an example array
vector<int> nums = {4, 4, 5, 5, 6, 7};
// Step 11: Create an object of Solution class
Solution sol;
// Step 12: Call the function and store the result
int ans = sol.secondMostFrequentElement(nums);
// Step 13: Print the result
cout << "The second highest occurring element in the array is: " << ans;
return 0;
}
Complexity Analysis:
- Time Complexity:
O(N^2)
, whereN
is the size of the array.- Using two nested loops.
- Space Complexity:
O(N)
- We are using visited array of size
N
.
- We are using visited array of size
2️⃣ Hashing (unordered_map)
Intuition:
An optimal approach to solve this question will be to use a Hashmap, a data structure that stores key-value pairs.
- Key will denote the element in the array.
- Value will store the frequency of the element in the array.
Approach:
To solve this problem, follow these steps:
- Initialize variables to keep track of the highest and second-highest frequencies, as well as the corresponding elements.
- Create a hashmap to store the frequency of each element in the array.
- Iterate through the array and update the frequency of each element in the hashmap.
- Iterate through the hashmap to determine the element with the highest frequency and the element with the second highest frequency.
- Return the element with the second highest frequency as the result.
Code:
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
// Function to get the second highest occurring element in array
int secondMostFrequentElement(vector<int> &nums) {
// Step 1: Get the size of the array
int n = nums.size();
// Step 2: Initialize frequency trackers
int maxFreq = 0; // Maximum frequency
int secMaxFreq = 0; // Second maximum frequency
// Step 3: Initialize element trackers
int maxEle = -1; // Element with maximum frequency
int secEle = -1; // Element with second maximum frequency
// Step 4: Create a hashmap to count frequencies of elements
unordered_map<int, int> mpp;
// Step 5: Iterate over the array and populate the frequency map
for (int i = 0; i < n; i++) {
mpp[nums[i]]++; // Increment frequency count for nums[i]
}
// Step 6: Iterate over the frequency map to determine max and second max
for (auto it : mpp) {
int ele = it.first; // Current element
int freq = it.second; // Its frequency
// Case 1: New max frequency found
if (freq > maxFreq) {
secMaxFreq = maxFreq; // Move current max to second max
maxFreq = freq; // Update max frequency
secEle = maxEle; // Move max element to second element
maxEle = ele; // Update max element
}
// Case 2: Tie with current max frequency (pick smaller element)
else if (freq == maxFreq) {
maxEle = min(maxEle, ele);
}
// Case 3: New second max frequency found
else if (freq > secMaxFreq) {
secMaxFreq = freq; // Update second max frequency
secEle = ele; // Update second element
}
// Case 4: Tie with second max frequency (pick smaller element)
else if (freq == secMaxFreq) {
secEle = min(secEle, ele);
}
}
// Step 7: Return the second most frequent element
return secEle;
}
};
int main() {
// Step 8: Define the input array
vector<int> nums = {4, 4, 5, 5, 6, 7};
// Step 9: Create an instance of the Solution class
Solution sol;
// Step 10: Call the function to get the second most frequent element
int ans = sol.secondMostFrequentElement(nums);
// Step 11: Print the result
cout << "The second highest occurring element in the array is: " << ans;
return 0;
}
Complexity Analysis:
- Time Complexity:
O(N)
, whereN
is the size of the array.O(N)
, loop for filling the map.O(k)
, for iterating over the map (wherek
is the number of unique elements).- In worst case,
k = n
(If all the elements are unique).
- In worst case,
- Space Complexity:
O(k)
, wherek
is the number of unique elements.- In worst case,
k = n
(If all elements are unique).
- In worst case,