Given a sorted integer array, find the floor and ceiling of a given number in it. The floor and ceiling map the given number to the largest previous or the smallest following integer in the array.

More precisely, for a number x, floor(x) is the largest integer in the array less than or equal to x, and ceil(x) is the smallest integer in the array greater than or equal to x. If the floor or ceil doesn’t exist, consider it to be -1. For example,

Input:
 
nums = [1, 4, 6, 8, 9]
Number: 0 to 10
 
Output:
 
Number 0 —> ceiling is 1, floor is -1
Number 1 —> ceiling is 1, floor is 1
Number 2 —> ceiling is 4, floor is 1
Number 3 —> ceiling is 4, floor is 1
Number 4 —> ceiling is 4, floor is 4
Number 5 —> ceiling is 6, floor is 4
Number 6 —> ceiling is 6, floor is 6
Number 7 —> ceiling is 8, floor is 6
Number 8 —> ceiling is 8, floor is 8
Number 9 —> ceiling is 9, floor is 9
Number 10 —> ceiling is -1, floor is 9

Practice this problem

A simple solution would be to run a linear search on the array and find the largest integer in the array less than or equal to x and the smallest integer in the array greater than or equal to x. That would be the floor and ceiling of the number x, respectively. The problem with this approach is that its worst-case time complexity is O(n), where n is the size of the input.

 
We can easily solve this problem in O(log(n)) time by modifying the binary search algorithm. The basic idea remains the same. We find the middle element and recur for the left or right subarray based on comparison result with the given number. Following is the complete algorithm:

findCeil(nums[low, high], x)

  • If x is less than equal to nums[low], nums[low] is the ceiling.
  • If x is more than nums[high], its ceiling doesn’t exist.
  • If x is equal to the middle element, it is the ceiling.
  • If x is more than the middle element, the ceiling exists in the right subarray nums[mid+1…high].
  • If x is less than the middle element, the ceiling exists in the left subarray nums[low…mid]. Here, include mid as part of the left subarray as the middle element can also be ceiling.

 
findFloor(nums[low, high], x)

  • If x is less than nums[low], its floor doesn’t exist.
  • If x is more than equal to the nums[high], it is the floor.
  • If x is equal to the middle element, it is the floor.
  • If x is more than the middle element, the floor exists in the right subarray nums[mid…high]. Here, include mid as part of the right subarray as the middle element can also be the floor.
  • If x is less than the middle element, the floor exists in the left subarray nums[low…mid-1].

The algorithm can be implemented as follows in C, Java, and Python:

C


Download  Run Code

Java


Download  Run Code

Python


Download  Run Code

Output:
 
Number 0 —> ceiling is 1, floor is -1
Number 1 —> ceiling is 1, floor is 1
Number 2 —> ceiling is 4, floor is 1
Number 3 —> ceiling is 4, floor is 1
Number 4 —> ceiling is 4, floor is 4
Number 5 —> ceiling is 6, floor is 4
Number 6 —> ceiling is 6, floor is 6
Number 7 —> ceiling is 8, floor is 6
Number 8 —> ceiling is 8, floor is 8
Number 9 —> ceiling is 9, floor is 9
Number 10 —> ceiling is -1, floor is 9

The time complexity of the above solution is O(log(n)) and requires O(log(n)) implicit space for the call stack.

 
Exercise: Write an iterative function to find the floor and ceil of a number.