Lower Bound

package com.thealgorithms.searches;

import static java.lang.String.format;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;
import com.thealgorithms.devutils.searches.SearchAlgorithm;

/**
 * The LowerBound method is used to return an index pointing to the first
 * element in the range [first, last) which has a value not less than val, i.e.
 * the index of the next smallest number just greater than or equal to that
 * number. If there are multiple values that are equal to val it returns the
 * index of the first such value.
 *
 * <p>
 * This is an extension of BinarySearch.
 *
 * <p>
 * Worst-case performance O(log n) Best-case performance O(1) Average
 * performance O(log n) Worst-case space complexity O(1)
 *
 * @author Pratik Padalia (https://github.com/15pratik)
 * @see SearchAlgorithm
 * @see BinarySearch
 */
class LowerBound implements SearchAlgorithm {

    // Driver Program
    public static void main(String[] args) {
        // Just generate data
        Random r = ThreadLocalRandom.current();

        int size = 100;
        int maxElement = 100000;

        Integer[] integers
                = IntStream.generate(() -> r.nextInt(maxElement))
                        .limit(size)
                        .sorted()
                        .boxed()
                        .toArray(Integer[]::new);

        // The element for which the lower bound is to be found
        int val = integers[r.nextInt(size - 1)] + 1;

        LowerBound search = new LowerBound();
        int atIndex = search.find(integers, val);

        System.out.println(
                format(
                        "Val: %d. Lower Bound Found %d at index %d. An array length %d",
                        val, integers[atIndex], atIndex, size));

        boolean toCheck = integers[atIndex] >= val || integers[size - 1] < val;
        System.out.println(
                format(
                        "Lower Bound found at an index: %d. Is greater or max element: %b", atIndex, toCheck));
    }

    /**
     * @param array is an array where the LowerBound value is to be found
     * @param key is an element for which the LowerBound is to be found
     * @param <T> is any comparable type
     * @return index of the LowerBound element
     */
    @Override
    public <T extends Comparable<T>> int find(T[] array, T key) {
        return search(array, key, 0, array.length - 1);
    }

    /**
     * This method implements the Generic Binary Search
     *
     * @param array The array to make the binary search
     * @param key The number you are looking for
     * @param left The lower bound
     * @param right The upper bound
     * @return the location of the key
     */
    private <T extends Comparable<T>> int search(T[] array, T key, int left, int right) {
        if (right <= left) {
            return left;
        }

        // find median
        int median = (left + right) >>> 1;
        int comp = key.compareTo(array[median]);

        if (comp == 0) {
            return median;
        } else if (comp < 0) {
            // median position can be a possible solution
            return search(array, key, left, median);
        } else {
            // key we are looking is greater, so we must look on the right of median position
            return search(array, key, median + 1, right);
        }
    }
}
Algerlogo

Β© Alger 2022

About us

We are a group of programmers helping each other build new things, whether it be writing complex encryption programs, or simple ciphers. Our goal is to work together to document and model beautiful, helpful and interesting algorithms using code. We are an open-source community - anyone can contribute. We check each other's work, communicate and collaborate to solve problems. We strive to be welcoming, respectful, yet make sure that our code follows the latest programming guidelines.