Given a sorted array of integers and a target element. Find the number of occurrences of the target in the array. You must write an algorithm with O(log n) runtime complexity.
OR
Given a sorted (ascending order) array of integers, find the number of occurrences of a given number x in the array.
Since the array is sorted, we can use binary search to efficiently find the first and last positions of the target. This is the problem we have already solved - Find first and last positions of target element in sorted array .The number of occurrences is simply last - first + 1 if the target exists.
classSolution {
public:int countOccurrences(const std::vector<int>& nums, int target) {
int first = findFirst(nums, target);
if (first ==-1) return0;
int last = findLast(nums, target);
return last - first +1;
}
private:int findFirst(const std::vector<int>& nums, int target) {
int left =0, right = nums.size() -1, ans =-1;
while (left <= right) {
int mid = left + (right - left) /2;
if (nums[mid] < target) left = mid +1;
elseif (nums[mid] > target) right = mid -1;
else {
ans = mid;
right = mid -1;
}
}
return ans;
}
intfindLast(const std::vector<int>& nums, int target) {
int left =0, right = nums.size() -1, ans =-1;
while (left <= right) {
int mid = left + (right - left) /2;
if (nums[mid] < target) left = mid +1;
elseif (nums[mid] > target) right = mid -1;
else {
ans = mid;
left = mid +1;
}
}
return ans;
}
};
classSolution {
publicintcountOccurrences(int[] nums, int target) {
int first = findFirst(nums, target);
if (first ==-1) return 0;
int last = findLast(nums, target);
return last - first + 1;
}
privateintfindFirst(int[] nums, int target) {
int left = 0, right = nums.length- 1, ans =-1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid]< target) left = mid + 1;
elseif (nums[mid]> target) right = mid - 1;
else {
ans = mid;
right = mid - 1;
}
}
return ans;
}
privateintfindLast(int[] nums, int target) {
int left = 0, right = nums.length- 1, ans =-1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid]< target) left = mid + 1;
elseif (nums[mid]> target) right = mid - 1;
else {
ans = mid;
left = mid + 1;
}
}
return ans;
}
}
classSolution {
funcountOccurrences(nums: IntArray, target: Int): Int {
val first = findFirst(nums, target)
if (first == -1) return0val last = findLast(nums, target)
return last - first + 1 }
privatefunfindFirst(nums: IntArray, target: Int): Int {
var left = 0; var right = nums.size - 1; var ans = -1while (left <= right) {
val mid = left + (right - left) / 2when {
nums[mid] < target -> left = mid + 1 nums[mid] > target -> right = mid - 1else-> { ans = mid; right = mid - 1 }
}
}
return ans
}
privatefunfindLast(nums: IntArray, target: Int): Int {
var left = 0; var right = nums.size - 1; var ans = -1while (left <= right) {
val mid = left + (right - left) / 2when {
nums[mid] < target -> left = mid + 1 nums[mid] > target -> right = mid - 1else-> { ans = mid; left = mid + 1 }
}
}
return ans
}
}
We can use two modified binary searches to find the leftmost index where nums[i] >= target and the rightmost index where nums[i] > target. The count is then right - left. This approach is similar to using lower_bound and upper_bound in C++ STL and can be implemented in one pass in some languages.
classSolution {
public:int countOccurrences(const std::vector<int>& nums, int target) {
int left = lowerBound(nums, target);
int right = lowerBound(nums, target +1);
if (left == nums.size() || nums[left] != target) return0;
return right - left;
}
private:int lowerBound(const std::vector<int>& nums, int target) {
int left =0, right = nums.size();
while (left < right) {
int mid = left + (right - left) /2;
if (nums[mid] < target) left = mid +1;
else right = mid;
}
return left;
}
};
funccountOccurrences(nums []int, targetint) int {
left:=lowerBound(nums, target)
right:=lowerBound(nums, target+1)
ifleft== len(nums) ||nums[left] !=target {
return0 }
returnright-left}
funclowerBound(nums []int, targetint) int {
left, right:=0, len(nums)
forleft < right {
mid:=left+ (right-left)/2ifnums[mid] < target {
left = mid+1 } else {
right = mid }
}
returnleft}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classSolution {
publicintcountOccurrences(int[] nums, int target) {
int left = lowerBound(nums, target);
int right = lowerBound(nums, target + 1);
if (left == nums.length|| nums[left]!= target) return 0;
return right - left;
}
privateintlowerBound(int[] nums, int target) {
int left = 0, right = nums.length;
while (left < right) {
int mid = left + (right - left) / 2;
if (nums[mid]< target) left = mid + 1;
else right = mid;
}
return left;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
classSolution {
funcountOccurrences(nums: IntArray, target: Int): Int {
val left = lowerBound(nums, target)
val right = lowerBound(nums, target + 1)
if (left == nums.size || nums[left] != target) return0return right - left
}
privatefunlowerBound(nums: IntArray, target: Int): Int {
var left = 0; var right = nums.size
while (left < right) {
val mid = left + (right - left) / 2if (nums[mid] < target) left = mid + 1else right = mid
}
return left
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
classSolution:
defcount_occurrences(self, nums: list[int], target: int) -> int:
deflower_bound(nums, target):
left, right =0, len(nums)
while left < right:
mid = (left + right) //2if nums[mid] < target:
left = mid +1else:
right = mid
return left
left = lower_bound(nums, target)
right = lower_bound(nums, target +1)
if left == len(nums) or nums[left] != target:
return0return right - left