Given a sorted array arr[] (which may contain duplicate elements) and an integer x, find the 0-based index of the first element greater than or equal to x. This element is called the ceil of x.
If no such element exists, return -1.
Note: If multiple occurrences of the ceil exist, return the index of its first occurrence.
Examples:
Input: arr[] = [1, 2, 8, 10, 11, 12, 19], x = 5
Output: 2
Explanation: Smallest number greater than 5 is 8, whose index is 2.Input: arr[] = [1, 2, 8, 10, 11, 12, 19], x = 20
Output: -1
Explanation: No element greater than 20 is found. So output is -1.Input: arr[] = [1, 1, 2, 8, 10, 11, 12, 19], x = 0
Output: 0
Explanation: Smallest number greater than 0 is 1, whose indices are 0 and 1. The index of the first occurrence is 0.
Table of Content
[Naive Approach] Linear Search - O(n) Time and O(1) Space
- If x is smaller than or equal to the first element, return 0, the index of the first element.
- Otherwise, traverse the array to find the first index i such that arr[i] >= x. Return i.
- If no such element exists, return -1.
#include <iostream>
#include <vector>
using namespace std;
int findCeil(vector<int> &arr, int x)
{
// If x fits before the first element
if (x <= arr[0])
return 0;
// Scan array to find the ceiling position
for (int i = 0; i < arr.size() - 1; i++)
{
// Exact match
if (arr[i] == x)
return i;
// x lies between arr[i] and arr[i+1]
if (arr[i] < x && arr[i + 1] >= x)
return i + 1;
}
// No ceiling found
return -1;
}
int main()
{
vector<int> arr = {1, 2, 8, 10, 10, 12, 19};
int x = 3;
int index = findCeil(arr, x);
cout << index << endl;
return 0;
}
#include <stdio.h>
int findCeil(int arr[], int n, int x)
{
// x fits before the first element
if (x <= arr[0])
return 0;
// Traverse to find ceiling index
for (int i = 0; i < n - 1; i++)
{
// Exact match
if (arr[i] == x)
return i;
// x lies between arr[i] and arr[i+1]
if (arr[i] < x && arr[i + 1] >= x)
return i + 1;
}
// Ceiling does not exist
return -1;
}
int main()
{
int arr[] = {1, 2, 8, 10, 10, 12, 19};
int n = sizeof(arr) / sizeof(arr[0]);
int x = 3;
int index = findCeil(arr, n, x);
printf("%d", index);
return 0;
}
class GFG {
static int findCeil(int[] arr, int x)
{
// x fits before the first element
if (x <= arr[0])
return 0;
// Linearly find the ceiling index
for (int i = 0; i < arr.length - 1; i++) {
// Exact match
if (arr[i] == x)
return i;
// x lies between arr[i] and arr[i+1]
if (arr[i] < x && arr[i + 1] >= x)
return i + 1;
}
// Ceiling not present
return -1;
}
public static void main(String[] args)
{
int[] arr = { 1, 2, 8, 10, 10, 12, 19 };
int x = 3;
int index = findCeil(arr, x);
System.out.println(index);
}
}
def findCeil(arr, x):
# x fits before the first element.
if x <= arr[0]:
return 0
# Search for the ceiling index.
for i in range(len(arr) - 1):
# Exact match.
if arr[i] == x:
return i
# x lies between arr[i] and arr[i + 1].
if arr[i] < x and arr[i + 1] >= x:
return i + 1
# Check the last element.
if arr[-1] >= x:
return len(arr) - 1
# Ceiling does not exist.
return -1
# Driver Code
if __name__ == "__main__":
arr = [1, 2, 8, 10, 10, 12, 19]
x = 3
index = findCeil(arr, x)
print(index)
using System;
class GFG {
static int findCeil(int[] arr, int x)
{
// x fits before the first element.
if (x <= arr[0])
return 0;
// Traverse to find ceiling index.
for (int i = 0; i < arr.Length - 1; i++) {
// Exact match.
if (arr[i] == x)
return i;
// x lies between arr[i] and arr[i + 1].
if (arr[i] < x && arr[i + 1] >= x)
return i + 1;
}
// Ceiling does not exist.
return -1;
}
static void Main()
{
int[] arr = { 1, 2, 8, 10, 10, 12, 19 };
int x = 3;
int index = findCeil(arr, x);
Console.WriteLine(index);
}
}
function findCeil(arr, x)
{
// x fits before the first element
if (x <= arr[0])
return 0;
// Find ceiling index linearly
for (let i = 0; i < arr.length - 1; i++) {
// Exact match
if (arr[i] === x)
return i;
// x lies between arr[i] and arr[i+1]
if (arr[i] < x && arr[i + 1] >= x)
return i + 1;
}
// Ceiling not found
return -1;
}
// Driver Code
const arr = [ 1, 2, 8, 10, 10, 12, 19 ];
const x = 3;
const index = findCeil(arr, x);
console.log(index);
Output
2
[Expected Approach] Binary Search - O(log n) Time and O(1) Space
Since the input array is sorted, we can use binary search.
- Find the mid point.
- Else If arr[mid] < x, go to the right side
- Else (arr[mid] >= x), we found a potential candidate for ceiling. Go to the left side and try finding a smaller value which is greater than or equal to x.
- If no such element exists, return -1. Otherwise, return the stored index.
Let us understand with an example:
arr = [1, 2, 8, 10, 10, 12, 19] , x = 3
Initial: lo = 0, hi = 6, mid = 3 -> arr[3] = 10 (res = 3, Move Left)
Step 2: lo = 0, hi = 2, mid = 1 -> arr[1] = 2 (Move Right)
Step 3: lo = 2, hi = 2, mid = 2 -> arr[2] = 8 (res = 2, Move Left)
Final: lo > hi, return res = 2
#include <iostream>
#include <vector>
using namespace std;
int findCeil(vector<int> &arr, int x)
{
int lo = 0, hi = arr.size() - 1, res = -1;
while (lo <= hi)
{
int mid = lo + (hi - lo) / 2;
// Move right if mid value is smaller
if (arr[mid] < x)
lo = mid + 1;
// Store candidate and search left
else
{
res = mid;
hi = mid - 1;
}
}
return res;
}
int main()
{
vector<int> arr = {1, 2, 8, 10, 10, 12, 19};
int x = 3;
int index = findCeil(arr, x);
cout << index << endl;
return 0;
}
#include <stdio.h>
int findCeil(int arr[], int n, int x)
{
int lo = 0, hi = n - 1, res = -1;
while (lo <= hi)
{
int mid = lo + (hi - lo) / 2;
// Search right half
if (arr[mid] < x)
lo = mid + 1;
// Save answer and search left
else
{
res = mid;
hi = mid - 1;
}
}
return res;
}
int main()
{
int arr[] = {1, 2, 8, 10, 10, 12, 19};
int n = sizeof(arr) / sizeof(arr[0]);
int x = 3;
int index = findCeil(arr, n, x);
printf("%d", index);
return 0;
}
public class GFG {
static int findCeil(int[] arr, int x)
{
int lo = 0, hi = arr.length - 1, res = -1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
// Go right if mid is smaller
if (arr[mid] < x)
lo = mid + 1;
// Update answer and go left
else {
res = mid;
hi = mid - 1;
}
}
return res;
}
public static void main(String[] args)
{
int[] arr = { 1, 2, 8, 10, 10, 12, 19 };
int x = 3;
int index = findCeil(arr, x);
System.out.println(index);
}
}
def findCeil(arr, x):
lo, hi = 0, len(arr) - 1
res = -1
while lo <= hi:
mid = lo + (hi - lo) // 2
# Move right if mid is smaller
if arr[mid] < x:
lo = mid + 1
# Save result and move left
else:
res = mid
hi = mid - 1
return res
# Driver Code
if __name__ == "__main__":
arr = [1, 2, 8, 10, 10, 12, 19]
x = 3
index = findCeil(arr, x)
print(index)
using System;
class GFG {
static int findCeil(int[] arr, int x)
{
int lo = 0, hi = arr.Length - 1, res = -1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
// Shift to right half.
if (arr[mid] < x)
lo = mid + 1;
// Store answer and go left.
else {
res = mid;
hi = mid - 1;
}
}
return res;
}
static void Main()
{
int[] arr = { 1, 2, 8, 10, 10, 12, 19 };
int x = 3;
int index = findCeil(arr, x);
Console.WriteLine(index);
}
}
function findCeil(arr, x)
{
let lo = 0, hi = arr.length - 1, res = -1;
while (lo <= hi) {
let mid = Math.floor(lo + (hi - lo) / 2);
// Move to right half
if (arr[mid] < x)
lo = mid + 1;
// Update result and move left
else {
res = mid;
hi = mid - 1;
}
}
return res;
}
// Driver Code
const arr = [ 1, 2, 8, 10, 10, 12, 19 ];
const x = 3;
const index = findCeil(arr, x);
console.log(index);
Output
2
[Alternate Approach] Library Methods - O(log n) Time and O(1) Space
We can use the following library methods in different languages.
The lower_bound() method in C++, Arrays.binarySearch() in Java and bisect_left() in Python, Array.BinarySearch() in C#. Javascript do not provide any built-in function for binary search, so we implemented it manually in the above code.
#include <bits/stdc++.h>
using namespace std;
int findCeil(vector<int> &arr, int x)
{
int n = arr.size();
// Find the first element greater than or equal to x.
auto itr = lower_bound(arr.begin(), arr.end(), x);
// Convert iterator to index.
int idx = itr - arr.begin();
// Check if ceiling element exists.
if (idx == n)
return -1;
return idx;
}
int main()
{
vector<int> arr = {1, 2, 8, 10, 11, 12, 19};
int x = 5;
int ans = findCeil(arr, x);
cout << ans << endl;
return 0;
}
import java.util.Arrays;
class GFG {
static int findCeil(int[] arr, int x)
{
int n = arr.length;
// Find the index using binary search.
int idx = Arrays.binarySearch(arr, x);
// Find the insertion point if x is not present.
if (idx < 0) {
idx = -(idx + 1);
}
else {
// Find the first occurrence if duplicates
// exist.
while (idx > 0 && arr[idx - 1] == x) {
idx--;
}
}
// Check if the ceiling element exists.
if (idx == n)
return -1;
return idx;
}
public static void main(String[] args)
{
int[] arr = { 1, 2, 8, 10, 11, 12, 19 };
int x = 5;
System.out.println(findCeil(arr, x));
}
}
from bisect import bisect_left
def findCeil(arr, x):
n = len(arr)
# Find the first index of an element >= x.
idx = bisect_left(arr, x)
# Check if the ceiling element exists.
if idx == n:
return -1
return idx
# Driver Code
if __name__ == "__main__":
arr = [1, 2, 8, 10, 11, 12, 19]
x = 5
print(findCeil(arr, x))
using System;
class GFG {
static int findCeil(int[] arr, int x)
{
int n = arr.Length;
// Find the index using binary search.
int idx = Array.BinarySearch(arr, x);
// Find the insertion point if x is not present.
if (idx < 0)
idx = ~idx;
else {
// Find the first occurrence if duplicates
// exist.
while (idx > 0 && arr[idx - 1] == x)
idx--;
}
// Check if the ceiling element exists.
if (idx == n)
return -1;
return idx;
}
static void Main()
{
int[] arr = { 1, 2, 8, 10, 11, 12, 19 };
int x = 5;
int index = findCeil(arr, x);
Console.WriteLine(index);
}
}
Output
2
Related Articles:Ā