2529. Maximum Count of Positive Integer and Negative Integer
Problem Description
In this problem, we are provided with a sorted array nums
which is in non-decreasing order. Our task is to find the maximum count of either positive integers or negative integers present in the array. It is important to note that the number 0
is considered neither positive nor negative. We need to return the higher count between the total number of positive integers and the number of negative integers in the array.
Intuition
Since the array is sorted in non-decreasing order, all negative numbers, if any, will be positioned at the beginning of the array, followed by zeroes and then positive numbers. Identifying the number of positive numbers can be done by finding the first occurrence of a number greater than or equal to 1
. The count of positive numbers is then the total length of the array minus the index of this first positive number. Similarly, the number of negative numbers is the index where the first non-negative number (which could be 0
) is located, as this index is equal to the count of negative numbers before it.
We can efficiently find these points of transition from negative to zero and from zero to positive using a binary search technique. The Python bisect
library offers functions like bisect_left
which can be leveraged for this purpose:
bisect_left(nums, 1)
will return the index of the first positive integer.bisect_left(nums, 0)
will give the index of the first non-negative integer, which is also the count of the negative integers.
Finally, we take the maximum between the count of positive numbers and negative numbers and return it as the solution. The use of binary search here allows the solution to be efficient even for large arrays.
Learn more about Binary Search patterns.
Solution Approach
The solution approach takes advantage of the sorted nature of the input array and binary search algorithm to efficiently find the count of negative and positive numbers. It uses the bisect
library in Python, which provides a collection of tools for handling sorted lists.
Here's a step-by-step breakdown of how the algorithm works:
-
Calculate the count of positive numbers by finding the index of the first positive integer. Since the array is sorted, all positive integers are at the end. The function
bisect_left(nums, 1)
finds the leftmost value greater than or equal to1
. This is essentially the index of the first positive number. The count of positive numbers is then the length of the array minus this index. -
Find the count of negative numbers by locating the index of the first non-negative integer (either
0
or the first positive).bisect_left(nums, 0)
will give us this index directly, which represents the total number of negative integers since they are all to the left of this point in the sorted array. -
The
max(a, b)
function is then used to compare the counts of positive numbers(a)
and negative numbers(b)
and return the larger of the two. This maximum value represents the largest group, either positive or negative numbers within the array.
The code uses bisect_left
twice on the sorted array, making the time complexity O(log n)
, where n
is the size of the array nums
. The space complexity is O(1)
because we are only storing two integers for the counts and the result, using no additional space proportionate to the input size.
In essence, the implementation leverages binary search to pinpoint the transition points within the array—the first transition from negative to either zero or positive and the second transition from zero to positive—and then uses simple arithmetic and the max
function to determine the answer.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's consider the following example array of sorted integers:
nums = [-4, -3, -2, 0, 2, 3, 5]
In this example, we shall walk through the algorithm steps based on the solution approach.
-
Find the count of positive numbers:
- We want to locate the index of the first positive integer. Since the array is non-decaying, we can use
bisect_left(nums, 1)
to find this point efficiently. - Applying
bisect_left(nums, 1)
to our example, we identify that the first occurrence of a number greater than or equal to1
is positioned at index4
where the value is2
. - The count of positive integers is then the total array length
7
minus the index4
, which equals3
. So there are3
positive numbers.
- We want to locate the index of the first positive integer. Since the array is non-decaying, we can use
-
Determine the count of negative numbers:
- Here, we aim to locate the index of the first non-negative number (
0
or a positive integer).bisect_left(nums, 0)
will help find that index. - In our example,
bisect_left(nums, 0)
returns index3
as the first location where the value0
or a number greater does not precede it. - This indicates that there are precisely
3
negative integers before the zero found at index3
.
- Here, we aim to locate the index of the first non-negative number (
-
Choose the maximum count:
- We need to decide which group is larger: negative numbers or positive numbers. By using the
max(a, b)
function wherea
is the number of positives andb
is the number of negatives, we can quickly infer the larger count. - Comparing
3
(positive count) and3
(negative count), we see that they are equal. Therefore, the function should return3
.
- We need to decide which group is larger: negative numbers or positive numbers. By using the
With these steps, the algorithm determines that the maximum count of either positive or negative integers in the array nums
is 3
. The efficient use of binary search allows us to conclude without having to iterate over the entire array, thus maintaining a time complexity of O(log n)
.
Solution Implementation
1from bisect import bisect_left
2from typing import List
3
4class Solution:
5 def maximumCount(self, nums: List[int]) -> int:
6 # Calculate the number of elements equal or greater than 1 using binary search.
7 # bisect_left returns the leftmost place in the sorted list to insert the number 1
8 # Subtract this from the length of the array to find the count of elements >= 1
9 count_ones_or_more = len(nums) - bisect_left(nums, 1)
10
11 # Calculate the number of elements which are negative using binary search.
12 # bisect_left returns the leftmost place in the sorted list to insert number 0
13 # It gives us the number of negative numbers since the list is sorted.
14 count_negative = bisect_left(nums, 0)
15
16 # Return the maximum of the two counts calculated
17 return max(count_ones_or_more, count_negative)
18
1class Solution {
2
3 // Method calculates the maximum count of either 0's or 1's in a sorted binary array
4 public int maximumCount(int[] nums) {
5 // Find the number of 1's by subtracting the index of the first 1 from the array length
6 int countOfOnes = nums.length - firstOccurrence(nums, 1);
7 // Find the first occurrence index of 0, which is also the count of 0's
8 int countOfZeros = firstOccurrence(nums, 0);
9 // Return the max count between 0's and 1's
10 return Math.max(countOfOnes, countOfZeros);
11 }
12
13 // Helper method to find the first occurrence index of 'x' in the sorted array 'nums'
14 private int firstOccurrence(int[] nums, int x) {
15 int left = 0;
16 int right = nums.length;
17 // Binary search to find the first occurrence of 'x'
18 while (left < right) {
19 int mid = (left + right) >> 1; // Equivalent to (left + right) / 2 but faster
20 // If mid element is greater than or equal to x, we move the right boundary
21 if (nums[mid] >= x) {
22 right = mid;
23 } else {
24 // If mid element is less than x, we move the left boundary
25 left = mid + 1;
26 }
27 }
28 // 'left' will point to the first occurrence of 'x' or nums.length if 'x' is not found
29 return left;
30 }
31}
32
1// Include the necessary header files
2#include <vector>
3#include <algorithm> // Needed for std::lower_bound function
4
5class Solution {
6public:
7 // Function to find the maximum count of elements greater than or equal to 1
8 // or the number of elements before the first occurrence of 1 in the sorted array.
9 int maximumCount(std::vector<int>& nums) {
10 // Find the number of elements that are greater than or equal to 1.
11 // This is done by finding the lower bound of 1 in the array,
12 // which gives an iterator to the first element not less than 1,
13 // and then calculating the distance from this iterator to the end of the array.
14 int countOfOnesOrGreater = nums.end() - std::lower_bound(nums.begin(), nums.end(), 1);
15
16 // Similar to the above, find the lower bound of 0, which is the first occurrence of 0,
17 // and then calculate the distance from the beginning of the array to this iterator.
18 // This is the number of elements that are less than 1.
19 int countBeforeFirstOne = std::lower_bound(nums.begin(), nums.end(), 0) - nums.begin();
20
21 // Return the maximum of the two counts calculated above.
22 return std::max(countOfOnesOrGreater, countBeforeFirstOne);
23 }
24};
25
1// Function that returns the maximum count of zeroes or ones by either
2// counting the number of zeroes from the start or the number of ones from the end
3function maximumCount(nums: number[]): number {
4 // Helper function to perform a binary search for the target value (0 or 1)
5 // and return the index of the first occurrence of the target in the sorted array
6 const binarySearch = (target: number): number => {
7 let left = 0; // Starting index of the search range
8 let right = nums.length; // Ending index of the search range (exclusive)
9
10 // While the search range is not empty
11 while (left < right) {
12 // Calculate the midpoint to divide the search range
13 const mid = (left + right) >>> 1; // Equivalent to Math.floor((left + right) / 2)
14
15 // Narrow down the search range based on the comparison with target
16 if (nums[mid] < target) {
17 left = mid + 1; // Target must be in the upper half of the range
18 } else {
19 right = mid; // Target is in the lower half or at the midpoint
20 }
21 }
22 // Return the final index where the target should be inserted
23 return left;
24 };
25
26 // Find the index of the first occurrence of 0 and 1 using binary search
27 const indexZero = binarySearch(0);
28 const indexOne = binarySearch(1);
29
30 // Calculate the maximum count of either zeroes or ones
31 // by choosing the higher count between the two
32 return Math.max(indexZero, nums.length - indexOne);
33}
34
Time and Space Complexity
Time Complexity
The given code consists mainly of two binary searches, one to find the index of the first occurrence of 1
using bisect_left(nums, 1)
and another one to find the index of the first occurrence of 0
using bisect_left(nums, 0)
. Since binary search has a time complexity of O(log n)
for a list of n
elements, and we are performing two binary searches, the overall time complexity of the function is O(log n)
.
Space Complexity
The implemented function does not create any additional data structures that grow with the input size. Thus, the space complexity is constant, O(1)
, regardless of the input size of nums
.
Learn more about how to find time and space complexity quickly using problem constraints.
What is the best way of checking if an element exists in an unsorted array once in terms of time complexity? Select the best that applies.
Recommended Readings
Binary Search Speedrun For each of the Speedrun questions you will be given a binary search related problem and a corresponding multiple choice question The multiple choice questions are related to the techniques and template s introduced in the binary search section It's recommended that you have gone through at
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!