Special Array With X Elements Greater Than or Equal X
Problem
You are given an array nums of non-negative integers. nums is considered special if there exists a number x such that there are exactly x numbers in nums that are greater than or equal to x.
Notice that x does not have to be an element in nums.
Return x if the array is special, otherwise, return -1. It can be proven that if nums is special, the value for x is unique.
Examples
Example 1:
Input: nums = [3,5]
Output: 2
Explanation: There are 2 values (3 and 5) that are greater than or equal to 2.
Example 2:
Input: nums = [0,0]
Output: -1
Explanation: No numbers fit the criteria for x.
If x = 0, there should be 0 numbers >= x, but there are 2.
If x = 1, there should be 1 number >= x, but there are 0.
If x = 2, there should be 2 numbers >= x, but there are 0.
x cannot be greater since there are only 2 numbers in nums.
Example 3:
Input: nums = [0,4,3,0,4]
Output: 3
Explanation: There are 3 values that are greater than or equal to 3.
Constraints
1 <= nums.length <= 1000 <= nums[i] <= 1000
Solution
Method 1 - Sorting
We saw in example 1, that even though 2 was not in the array, there exists x=2 where there are 2 values which are greater than x=2.
Suppose, we have input nums = [2], then x = 1. ⇨ So, this x is between 1 and n, where n is the length of the array.
So, sorting the elements(say in ascending order) can help us. Also, in eg 1, we see that array is sorted, and nums[0] > n, so n is the answer.
Video explanation
Here is the video explaining this method in detail. Please check it out:
<div class="youtube-embed"><iframe src="https://www.youtube.com/embed/qxZ0I8TbZ7c" frameborder="0" allowfullscreen></iframe></div>
Algorithm
Lets look at example 3 for this.
- Sort the array (
[0,4,3,0,4]⇨[0,0,3,4,4]) - Now, iterate on array with iterator say
xfrom1ton(n = 5). Now, we try to find the pivot point from the end of the array such thatnums[pivot] >= xandnums[pivot - 1] < x. Lets call this element possiblecandidate.- Define a
candidateposition in array asn - x(we know that forx=3there should be 3 numbers in range, lets sayx=3, our candidate position is5-3 = 2) - If value of
candidateis>= xand previous number is< x- we foundx:nums[candidate]= 3 >= 3 andnums[candidate-1]= 0 < 3. - So, we found our X.
- Define a
Why use n-x?
Here's how n - x works with respect to x:
- Since
nis the total number of elements in the array,n - 1would be the index of the last element - If we're looking for exactly
xelements that are greater than or equal tox, that means there aren - xelements that are less thanx. - Therefore,
n - xsignifies the starting point (index) where we expect to find elements that are greater than or equal tox. In other words, ifxis the special number,nums[n - x]should be greater than or equal tox, andnums[n - x - 1]should be less thanx(since it's the first element that isn't part of thexelements greater than or equal tox).
With the array sorted in non-decreasing order, this means that at index n - x we transition from elements less than x to elements that are at least x or more, where x is the candidate for our "special" number. If we find that the element at index n - x is indeed greater than or equal to x and the one right before it (at index n - x - 1) is less than x, then x fits the definition of the "special" number, and we have found our answer.
Visualization
Let array be:
index = 0 1 2 3 4
nums = | 1 | 2 | 3 | 4 | 5 |
n = 5
Lets see some values of x and candidates:
x = 1
x = 1, candidate = n - x => 4; nums[candidate] = 5
nums = | 1 | 2 | 3 | 4 | 5 |
^ ^
x n-x
x = 2
x = 2, candidate = n - x => 3; nums[candidate] = 4
nums = | 1 | 2 | 3 | 4 | 5 |
^ ^
x n-x
x = 3
x = 3, candidate = n - x => 2; nums[candidate] = 3
nums = | 1 | 2 | 3 | 4 | 5 |
^
x
n-x
Clearly x = 3 is our answer, as n-x is the right pivot points.
Code
Java
class Solution {
public int specialArray(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
if (nums[0] >= n) {
return n;
}
for (int x = 1; x <= n; x++) {
int candidate = n - x;
if (nums[candidate] >= x && nums[candidate - 1] < x) {
return x;
}
}
return -1;
}
}
Complexity
-
⏰ Time complexity:
O(n log n)(O(nlogn)for sorting, andO(n)for going through sorted array) -
🧺 Space complexity:
O(1)
Method 2 - Using Counting sort
Code
class Solution {
public int specialArray(int[] nums) {
bucketSort(nums);
int n = nums.length;
if (nums[0] >= n) {
return n;
}
for (int x = 1; x <= n; x++) {
int candidate = n - x;
if (nums[candidate] >= x && nums[candidate - 1] < x) {
return x;
}
}
return -1;
}
private void bucketSort(int[] nums) {
int numBuckets = 1001;
int[] buckets = new int[numBuckets];
for (int num : nums) {
buckets[num]++;
}
int index = 0;
for (int i = 0; i < numBuckets; i++) {
// Add the elements from each bucket back to the original array
for (int j = 0; j < buckets[i]; j++) {
nums[index++] = i;
}
}
}
}
Complexity
- ⏰ Time complexity:
O(n)(O(n)for sorting andO(n)for iterating onnums). - 🧺 Space complexity:
O(1)(For bucket sort we use O(1001)space, i.e.O(1))