Given a sorted array of integers nums, count the number of occurrences of a given value.
Example:
Input: nums = [1, 2, 2, 2, 4, 5]
, value = 2
Output: 3
Explanation: the value 2 appears 3 times in the array
Your algorithm should run in O(log n) time and use O(1) extra space.
The core challenge of this problem is to efficiently count the number of occurrences of a given value in a sorted array. The significance of this problem lies in its applications in search algorithms and data analysis, where quick lookups are essential. A common pitfall is to use a linear search, which would result in O(n) time complexity, not meeting the problem's requirements.
To solve this problem efficiently, we can use binary search to find the first and last occurrences of the given value. The difference between these indices plus one will give us the count of occurrences.
A naive solution would involve iterating through the array and counting the occurrences of the value. This approach has a time complexity of O(n), which is not optimal for large arrays.
We can optimize the solution using binary search to find the first and last occurrences of the value. This approach leverages the sorted nature of the array and achieves O(log n) time complexity.
We use a modified binary search to find the first occurrence of the value. If the middle element is greater than or equal to the value, we move the search to the left half; otherwise, we move to the right half.
Similarly, we use a modified binary search to find the last occurrence. If the middle element is less than or equal to the value, we move the search to the right half; otherwise, we move to the left half.
Here is a step-by-step breakdown of the algorithm:
#include <iostream>
#include <vector>
using namespace std;
// Function to find the first occurrence of value
int findFirstOccurrence(const vector<int>& nums, int value) {
int left = 0, right = nums.size() - 1, ans = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] >= value) {
if (nums[mid] == value) ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}
// Function to find the last occurrence of value
int findLastOccurrence(const vector<int>& nums, int value) {
int left = 0, right = nums.size() - 1, ans = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] <= value) {
if (nums[mid] == value) ans = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return ans;
}
// Function to count the number of occurrences of value
int countOccurrences(const vector<int>& nums, int value) {
int first = findFirstOccurrence(nums, value);
if (first == -1) return 0; // Value not found
int last = findLastOccurrence(nums, value);
return last - first + 1;
}
int main() {
vector<int> nums = {1, 2, 2, 2, 4, 5};
int value = 2;
cout << "Number of occurrences of " << value << ": " << countOccurrences(nums, value) << endl;
return 0;
}
The time complexity of both binary search functions is O(log n), and since we perform two binary searches, the overall time complexity is O(log n). The space complexity is O(1) as we are not using any extra space apart from a few variables.
Potential edge cases include:
Our algorithm handles these cases by returning 0 if the value is not found and correctly calculating the occurrences otherwise.
To test the solution comprehensively, consider the following test cases:
When approaching such problems, consider the following tips:
In this blog post, we discussed how to count the number of occurrences of a value in a sorted array using an efficient O(log n) algorithm. We explored the problem definition, approach, algorithm, code implementation, complexity analysis, edge cases, and testing. Understanding and solving such problems is crucial for improving your algorithmic thinking and coding skills.
For further reading and practice, consider the following resources: