Find Occurrences of an Element in an Array
MedPrompt
You are given an integer array nums, an integer array queries, and an integer x.
For each queries[i], you need to find the index of the queries[i]th occurrence of x in the nums array. If there are fewer than queries[i] occurrences of x, the answer should be -1 for that query.
Return an integer array answer containing the answers to all queries.
Example 1:
Input: nums = [1,3,1,7], queries = [1,3,2,4], x = 1
Output: [0,-1,2,-1]
Explanation:
- For the 1st query, the first occurrence of 1 is at index 0.
- For the 2nd query, there are only two occurrences of 1 in
nums, so the answer is -1. - For the 3rd query, the second occurrence of 1 is at index 2.
- For the 4th query, there are only two occurrences of 1 in
nums, so the answer is -1.
Example 2:
Input: nums = [1,2,3], queries = [10], x = 5
Output: [-1]
Explanation:
- For the 1st query, 5 doesn't exist in
nums, so the answer is -1.
Constraints:
1 <= nums.length, queries.length <= 1051 <= queries[i] <= 1051 <= nums[i], x <= 104
Approaches
2 approaches with complexity analysis and trade-offs.
This is a straightforward, brute-force solution. For each query, we perform a full scan of the nums array from the beginning. We keep a count of the occurrences of x we've seen so far. When the count matches the desired occurrence number from the query, we record the current index and move to the next query. If we scan the entire array and don't find the required number of occurrences, the answer for that query is -1.
Algorithm
- Initialize an integer array
answerwith the same length asqueries. - Iterate through each query
kat indexiin thequeriesarray. - For each
k, initialize a countercountto 0 and a variablefoundIndexto -1. - Iterate through the
numsarray from left to right with indexj. - If
nums[j]is equal to the target valuex, incrementcount. - If
countbecomes equal tok, it means we have found thek-th occurrence. SetfoundIndexto the current indexjand break the inner loop. - After the inner loop finishes, assign
foundIndextoanswer[i]. - After iterating through all queries, return the
answerarray.
Walkthrough
The core idea is to process each query independently. For a query asking for the k-th occurrence, we iterate through nums and count how many times we've encountered x. When our count reaches k, the index at that point is our answer. This process is repeated for every single query in the queries array.
class Solution { public int[] occurrencesOfElement(int[] nums, int[] queries, int x) { int[] answer = new int[queries.length]; for (int i = 0; i < queries.length; i++) { int k = queries[i]; int count = 0; int foundIndex = -1; for (int j = 0; j < nums.length; j++) { if (nums[j] == x) { count++; if (count == k) { foundIndex = j; break; // Found the k-th occurrence, no need to search further for this query } } } answer[i] = foundIndex; } return answer; }}Complexity
Time
O(N * Q), where N is the length of `nums` and Q is the length of `queries`. In the worst-case scenario, for each of the Q queries, we may need to traverse the entire `nums` array.
Space
O(Q) to store the answer array. Excluding the output array, the space complexity is O(1) as we only use a few variables to process each query.
Trade-offs
Pros
Simple to understand and implement.
Uses O(1) extra space (if the output array is not considered).
Cons
Extremely inefficient for large inputs due to its nested loop structure.
The time complexity is quadratic, O(N * Q), which will lead to a 'Time Limit Exceeded' (TLE) error on platforms like LeetCode given the problem constraints.
This optimized approach avoids the redundant work of the brute-force method. Instead of scanning the nums array for every query, we can pre-process it. We do a single pass through nums to find and store the indices of all occurrences of x. Once we have this list of indices, answering each query becomes a simple and fast lookup operation.
Algorithm
- Create a dynamic list, for example, an
ArrayListin Java, to store the indices of all occurrences ofx. Let's call itxIndices. - Iterate through the
numsarray once fromi = 0tonums.length - 1. - If
nums[i]is equal tox, add the indexito thexIndiceslist. - Initialize an integer array
answerwith the same length asqueries. - Iterate through each query
kat indexiin thequeriesarray. - The
k-th occurrence corresponds to the indexk-1in ourxIndiceslist (since lists are 0-indexed). - Check if
kis a valid occurrence number, i.e., ifk > 0andk <= xIndices.size(). - If it is valid, the answer is
xIndices.get(k - 1). Assign this value toanswer[i]. - If it is not valid, it means there are fewer than
koccurrences ofx. Assign -1 toanswer[i]. - After processing all queries, return the
answerarray.
Walkthrough
The key insight is to decouple the search for x from the processing of queries. We first build a data structure that maps the occurrence number to its index in the original array. A simple list or dynamic array is perfect for this. The first element in our list is the index of the 1st occurrence, the second element is the index of the 2nd occurrence, and so on.
After this one-time setup which takes O(N) time, each query k can be answered in O(1) time by checking if the k-th element exists in our list (i.e., if k-1 is a valid index) and retrieving it if it does.
import java.util.ArrayList;import java.util.List; class Solution { public int[] occurrencesOfElement(int[] nums, int[] queries, int x) { // Step 1 & 2: Pre-compute and store indices of x List<Integer> xIndices = new ArrayList<>(); for (int i = 0; i < nums.length; i++) { if (nums[i] == x) { xIndices.add(i); } } // Step 3 & 4: Process queries using the pre-computed list int[] answer = new int[queries.length]; for (int i = 0; i < queries.length; i++) { int k = queries[i]; // Step 5, 6, 7: Check validity and retrieve the index // k is 1-based, list indices are 0-based if (k > 0 && k <= xIndices.size()) { answer[i] = xIndices.get(k - 1); } else { answer[i] = -1; } } return answer; }}Complexity
Time
O(N + Q), where N is the length of `nums` and Q is the length of `queries`. The algorithm consists of one pass over `nums` (O(N)) and one pass over `queries` (O(Q)). This is the optimal time complexity.
Space
O(K + Q), where K is the number of occurrences of `x` in `nums` (K <= N) and Q is the length of `queries`. The space is used for the `xIndices` list and the `answer` array. In the worst case, this is O(N + Q).
Trade-offs
Pros
Highly efficient with a linear time complexity, making it suitable for large inputs.
Answers each query in constant time after the initial pre-computation.
Cons
Requires extra space to store the indices of
x. In the worst case, if all elements innumsarex, this space can be O(N).
Solutions
Solution
class Solution {public int[] occurrencesOfElement(int[] nums, int[] queries, int x) { List<Integer> ids = new ArrayList<>(); for (int i = 0; i < nums.length; ++i) { if (nums[i] == x) { ids.add(i); } } int m = queries.length; int[] ans = new int[m]; for (int i = 0; i < m; ++i) { int j = queries[i] - 1; ans[i] = j < ids.size() ? ids.get(j) : -1; } return ans; }}class Solution {public: vector<int> occurrencesOfElement(vector<int> &nums, vector<int> &queries, int x) { vector<int> ids; for (int i = 0; i < nums.size(); ++i) { if (nums[i] == x) { ids.push_back(i); } } vector<int> ans; for (int &i : queries) { ans.push_back(i - 1 < ids.size() ? ids[i - 1] : -1); } return ans; }};class Solution: def occurrencesOfElement(self, nums: List[int], queries: List[int], x: int) -> List[int]: ids = [i for i, v in enumerate(nums) if v == x] return [ids[i - 1] if i - 1 < len(ids) else - 1 for i in queries]Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.