Count Occurrences of Element in Sorted Array in DSA Javascript - Time & Space Complexity
We want to know how fast we can count how many times a number appears in a sorted list.
How does the time needed change when the list gets bigger?
Analyze the time complexity of the following code snippet.
function countOccurrences(arr, target) {
function findFirst() {
let left = 0, right = arr.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (arr[mid] < target) left = mid + 1;
else right = mid - 1;
}
return left;
}
function findLast() {
let left = 0, right = arr.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (arr[mid] > target) right = mid - 1;
else left = mid + 1;
}
return right;
}
const first = findFirst();
const last = findLast();
if (first > last) return 0;
return last - first + 1;
}
This code finds the first and last positions of the target number using binary search, then calculates how many times it appears.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two binary search loops that repeatedly cut the search range in half.
- How many times: Each binary search runs about log2(n) times, where n is the array size.
Each binary search cuts the search space in half each step, so the number of steps grows slowly as the list grows.
| Input Size (n) | Approx. Operations (per binary search) |
|---|---|
| 10 | About 4 |
| 100 | About 7 |
| 1000 | About 10 |
Pattern observation: Doubling the input size adds only one more step, so growth is very slow.
Time Complexity: O(log n)
This means the time to count occurrences grows slowly, even if the list gets very large.
[X] Wrong: "Counting occurrences requires checking every element, so it must be O(n)."
[OK] Correct: Because the array is sorted, we can use binary search to jump directly to the first and last positions, avoiding checking every element.
Knowing how to use binary search to count occurrences shows you understand how to use sorting to speed up searching, a key skill in many coding challenges.
"What if the array was not sorted? How would the time complexity change?"
Practice
Solution
Step 1: Understand binary search efficiency
Binary search divides the search space in half each time, making it faster than checking every element.Step 2: Compare linear vs binary search
Linear search checks each element one by one (O(n)), binary search works in O(log n) time.Final Answer:
It reduces the search time from linear to logarithmic. -> Option BQuick Check:
Binary search = faster search [OK]
- Thinking binary search sorts the array
- Assuming binary search works on unsorted arrays
- Confusing counting with searching
arr between indices low and high in JavaScript?Solution
Step 1: Calculate middle index correctly
We use Math.floor to get the integer index because array indices must be whole numbers.Step 2: Avoid floating point and wrong calculations
Using just division or Math.ceil can cause errors or out-of-bound indices.Final Answer:
const mid = Math.floor((low + high) / 2); -> Option DQuick Check:
Use Math.floor for middle index [OK]
- Not using Math.floor causing float index
- Using Math.ceil which may skip elements
- Adding indices without division
function countOccurrences(arr, x) {
let low = 0, high = arr.length - 1;
let count = 0;
while (low <= high) {
let mid = Math.floor((low + high) / 2);
if (arr[mid] === x) {
count++;
let left = mid - 1;
while (left >= 0 && arr[left] === x) {
count++;
left--;
}
let right = mid + 1;
while (right < arr.length && arr[right] === x) {
count++;
right++;
}
break;
} else if (arr[mid] < x) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return count;
}
console.log(countOccurrences([1,2,2,2,3,4,5], 2));Solution
Step 1: Find one occurrence of 2 using binary search
The binary search finds 2 at index 2 (middle of array).Step 2: Count all adjacent 2s on left and right
Left side: indices 1 and 0 checked; only index 1 has 2. Right side: index 3 has 2. Total count = 3.Final Answer:
3 -> Option CQuick Check:
Count adjacent 2s = 3 [OK]
- Counting only the found element once
- Not checking neighbors on both sides
- Incorrect loop conditions causing infinite loops
x in a sorted array arr. What is the bug?function countOccurrences(arr, x) {
let low = 0, high = arr.length - 1;
let count = 0;
while (low <= high) {
let mid = Math.floor((low + high) / 2);
if (arr[mid] === x) {
count++;
let left = mid - 1;
while (arr[left] === x) {
count++;
left--;
}
let right = mid + 1;
while (arr[right] === x) {
count++;
right++;
}
break;
} else if (arr[mid] < x) {
low = mid + 1;
} else {
high = mid - 1;
}
}
return count;
}Solution
Step 1: Analyze while loops for boundary checks
The loops checkarr[left] === xandarr[right] === xwithout verifying ifleftorrightare valid indices.Step 2: Identify risk of out-of-bounds access
Ifleftbecomes -1 orrightexceeds array length, accessingarr[left]orarr[right]causes errors.Final Answer:
The while loops do not check array bounds before accessing elements. -> Option AQuick Check:
Always check array bounds before access [OK]
- Ignoring array index limits in loops
- Assuming array access is always safe
- Not breaking loop on invalid index
arr = [1,2,2,2,3,3,4,5,5,5,5,6], which approach is the most efficient to count occurrences of 5 without scanning the entire array?Solution
Step 1: Understand the problem constraints
The array is sorted, so all 5s are grouped together.Step 2: Use binary search to find boundaries
Find the first index of 5 and last index of 5 using binary search, then count = last - first + 1.Step 3: Compare efficiency
This method is O(log n), faster than scanning entire array (O(n)) or sorting again (O(n log n)).Final Answer:
Use binary search to find first and last positions of 5, then calculate count. -> Option AQuick Check:
Binary search boundaries = efficient count [OK]
- Scanning entire array unnecessarily
- Sorting already sorted array again
- Using extra space with hash map when not needed
Ready to prove it?
Pass the test and this pattern moves unknown
