Classical Binary Search

Latest LeetCode problem deals with classical binary search, here it is: https://leetcode.com/problems/find-smallest-letter-greater-than-target/description/

Given a list of sorted characters letters containing only lowercase letters, and given a target letter target, find the smallest element in the list that is larger than the given target.
Letters also wrap around. For example, if the target is target = 'z' and letters = ['a', 'b'], the answer is 'a'.
Examples:
Input:
letters = ["c", "f", "j"]
target = "a"
Output: "c"

Input:
letters = ["c", "f", "j"]
target = "c"
Output: "f"

Input:
letters = ["c", "f", "j"]
target = "d"
Output: "f"

Input:
letters = ["c", "f", "j"]
target = "g"
Output: "j"

Input:
letters = ["c", "f", "j"]
target = "j"
Output: "c"

Input:
letters = ["c", "f", "j"]
target = "k"
Output: "c"

It is easy to read the hints here: ordered list, looking for a specific element in that list. Don't worry too much about the statement "it also wraps around". To handle this case add a simple check in the very beginning of the code checking whether the target is greater than or equal to the last element in "letters". If so, return the first element. Other than that, the rest of the code is a traditional, no-catches, binary search program. Hope you enjoy, Marcelo.



public class Solution
{
public char NextGreatestLetter(char[] letters, char target)
{
if (target >= letters[letters.Length - 1]) return letters[0];

int left = 0;
int right = letters.Length - 1;
while (left < right)
{
int mid = (left + right) / 2;
if (target >= letters[mid]) left = mid + 1;
else right = mid;
}

return letters[left];
}
}

Comments

  1. Beautiful solution, Marcelo! There are 2 things that I'm usually trying to avoid though - (left + right) can lead to overflows (not relevant for this problem though, because the range is so limited) and right = mid makes it slightly less obvious that at every step we are shrinking the range. My ugly solution is below:

    class Solution {
    public:
    char nextGreatestLetter(const vector& letters, char target) {
    int left = 0;
    int right = letters.size() - 1;
    char candidate = 0;
    while (left <= right) {
    int mid = left + (right - left) / 2;
    if (letters[mid] <= target) {
    left = mid + 1;
    } else {
    candidate = letters[mid];
    right = mid - 1;
    }
    }
    return candidate == 0 ? letters.front() : candidate;
    }
    };

    Cheers,
    Taras

    ReplyDelete
  2. Love it! Your attention to details is nothing short of spectacular!!!

    ReplyDelete
    Replies
    1. haha, I wish it was :) Btw, if you like binary search, you may also like https://leetcode.com/problems/search-a-2d-matrix ;)

      Delete

Post a Comment

Popular posts from this blog

Advent of Code - Day 6, 2024: BFS and FSM

Golang vs. C#: performance characteristics (simple case study)

Advent of Code - Day 7, 2024: Backtracking and Eval