Floor and Ceiling in a Sorted Set

medium Java Collections

Problem

Keep a set of integers. Commands: insert X (prints ok, a repeated value is ignored), floor X (prints the biggest value in the set that is at most X) and ceil X (prints the smallest value in the set that is at least X). Print none if there is no such value.

Constraints

  • 1 <= commands <= 10^5

Examples

Input

insert 10
insert 20
floor 15
ceil 15
floor 5

Output

ok
ok
10
20
none

Solutions

Best approachTime O(log n) per query (O(n) insert in arrays)Space O(n)

Java's TreeSet gives floor and ceiling directly. JavaScript has no sorted set, and Python's list needs the bisect module. Knowing the idea (binary search on a sorted structure) lets you do it in any language.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process lines.
 * Input   : Several lines.
 * Output  : One answer per command.
 * Approach: A sorted set and binary search.
 * Time    : O(log n) per query (O(n) insert in arrays)
 * Space   : O(n)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static String[] solve(String[] lines) {
        // Step 1: A TreeSet keeps its values sorted. floor and ceiling find the nearest values in O(log n).
        java.util.TreeSet<Long> set = new java.util.TreeSet<>();
        String[] output = new String[lines.length];

        for (int i = 0; i < lines.length; i++) {
            String[] part = lines[i].split(" ");
            long value = Long.parseLong(part[1]);

            if (part[0].equals("insert")) {
                set.add(value);
                output[i] = "ok";
            } else if (part[0].equals("floor")) {
                // Step 2: floor = the biggest value that is at most the query. null means there is none.
                Long found = set.floor(value);
                output[i] = found == null ? "none" : String.valueOf(found);
            } else {
                // Step 3: ceiling = the smallest value that is at least the query.
                Long found = set.ceiling(value);
                output[i] = found == null ? "none" : String.valueOf(found);
            }
        }
        return output;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        java.util.List<String> all = new java.util.ArrayList<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (!line.isEmpty()) {
                all.add(line);
            }
        }
        String[] lines = all.toArray(new String[0]);
        System.out.println(String.join("\n", solve(lines)));
    }
}
Hints (1)
  1. Which structure gives floor() and ceiling() in Java?