Find Smallest Letter Greater Than Target

🏠 ⬅️ ➡️

You are given an array of characters letters that is sorted in non-decreasing order, and a character target. There are at least two different characters in letters.

Return the smallest character in letters that is lexicographically greater than target. If such a character does not exist, return the first character in letters.

Example 1:

Input: letters = [ "c ", "f ", "j "], target = "a " Output: "c " Explanation: The smallest character that is lexicographically greater than 'a' in letters is 'c'.

Example 2:

Input: letters = [ "c ", "f ", "j "], target = "c " Output: "f " Explanation: The smallest character that is lexicographically greater than 'c' in letters is 'f'.

Example 3:

Input: letters = [ "x ", "x ", "y ", "y "], target = "z " Output: "x " Explanation: There are no characters in letters that is lexicographically greater than 'z' so we return letters[0].

Constraints:

  • 2 <= letters.length <= 104
  • letters[i] is a lowercase English letter.
  • letters is sorted in non-decreasing order.
  • letters contains at least two different characters.
  • target is a lowercase English letter.

Note: This problem is from LeetCode.
Compiled
Executed
Correct
program main
    implicit none

    character(len=1), parameter :: letters(*) = ["c", "f", "j"]
    character(len=1) :: target = "a"
    character(len=1) :: result

    result = next_larger_letter(letters, target)
    print *, result

contains

    function next_larger_letter(letters, target) result(result_)
        implicit none
        character(len=1), intent(in) :: letters(:)
        character(len=1), intent(in) :: target
        character(len=1) :: result_
        integer :: i

        do i = 1, size(letters)
            if (letters(i) > target) then
                result_ = letters(i)
                exit
            end if
        end do

        if (result_ == "") then
            result_ = letters(1)
        end if
    end function next_larger_letter
end program main
Compiled
Executed
Correct
module FindSmallestLexicographicallyGreater
    implicit none

contains

    function findSmallestLexicographicallyGreater(letters, target) result(result)
        character(len=*), intent(in) :: letters(:)
        character(len=*), intent(in) :: target
        character(len=1) :: result

        integer :: i

        do i = 1, size(letters)
            if (letters(i) > target) then
                result = letters(i)
                exit
            end if
        end do

        if (result == '') then
            result = letters(1)
        end if
    end function findSmallestLexicographicallyGreater
end module FindSmallestLexicographicallyGreater

program test_findSmallestLexicographicallyGreater
    use FindSmallestLexicographicallyGreater
    implicit none

    character(len=1) :: result
    character(len=*), parameter :: letters = ["c ", "f ", "j "]

    result = findSmallestLexicographicallyGreater(letters, "a ")
    write (*, '(a)') 'Example 1: ' // result

    result = findSmallestLexicographicallyGreater(letters, "c ")
    write (*, '(a)') 'Example 2: ' // result

    result = findSmallestLexicographicallyGreater(["x ", "x ", "y ", "y "], "z ")
    write (*, '(a)') 'Example 3: ' // result
end program test_findSmallestLexicographicallyGreater
🌐 Data from online sources
import heapq
from collections import defaultdict

def networkDelayTime(times, n, k):
    graph = defaultdict(list)
    for u, v, w in times:
        graph[u].append((v, w))

    dist = {i: float('inf') for i in range(1, n + 1)}
    dist[k] = 0

    pq = [(0, k)]

    while pq:
        time, node = heapq.heappop(pq)

        if time > dist[node]:
            continue

        for neighbour, neighbourTime in graph[node]:
            candidate_dist = time + neighbourTime
            if candidate_dist < dist[neighbour]:
                dist[neighbour] = candidate_dist
                heapq.heappush(pq, (candidate_dist, neighbour))

    maxTime = max(dist.values())
    return maxTime if maxTime < float('inf') else -1

The algorithm uses Dijkstra's shortest path algorithm to find the shortest time it takes for the signal to reach every node.

  1. Create an adjacency list (graph) to represent the times between nodes. (note: we use different data structures depending on the language, but the idea is the same)
  2. Initialize a distance array (dist) to store the shortest time it takes for the signal to arrive at each node. Set the initial values to infinity (maximum possible time) except for node k, which is set to 0 as it's the source.
  3. Create a priority queue (pq) to store the time it takes to visit a node. Initialize it with node k and time 0.
  4. Iterate through the priority queue while it's not empty: a. Pop the node with the smallest time from the priority queue. b. Check if the current time is greater than the distance for the current node; if true, continue to the next iteration. c. For each neighbor's node in the graph, compare the sum of the current time and travel time to reach the neighbor with the minimum distance for the neighbor in the dist array. If the new calculated time is less, update the dist array and push the neighbor with the new calculated time into the priority queue.
  5. After the loop is finished, find the maximum value in the dist array (ignoring the first value, which is a placeholder). If the maximum value is infinity, return -1, as not all nodes could receive the signal. Otherwise, return the maximum time.
🌐 Data from online sources
#include <vector>
#include <queue>
#include <algorithm>
#include <limits>

int networkDelayTime(std::vector<std::vector<int>>& times, int n, int k) {
    std::vector<std::vector<std::pair<int, int>>> graph(n + 1);
    for (const auto &edge : times)
        graph[edge[0]].emplace_back(edge[1], edge[2]);

    std::vector<int> dist(n + 1, std::numeric_limits<int>::max());
    dist[k] = 0;

    std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> pq;
    pq.emplace(0, k);

    while (!pq.empty()) {
        int time = pq.top().first, node = pq.top().second;
        pq.pop();

        if (time > dist[node]) continue;
        for (const auto &neighbour : graph[node]) {
            int nextNode = neighbour.first, nextTime = neighbour.second;
            if (time + nextTime < dist[nextNode]) {
                dist[nextNode] = time + nextTime;
                pq.push({dist[nextNode], nextNode});
            }
        }
    }

    int maxTime = *std::max_element(dist.begin() + 1, dist.end());
    return maxTime == std::numeric_limits<int>::max() ? -1 : maxTime;
}

The algorithm uses Dijkstra's shortest path algorithm to find the shortest time it takes for the signal to reach every node.

  1. Create an adjacency list (graph) to represent the times between nodes. (note: we use different data structures depending on the language, but the idea is the same)
  2. Initialize a distance array (dist) to store the shortest time it takes for the signal to arrive at each node. Set the initial values to infinity (maximum possible time) except for node k, which is set to 0 as it's the source.
  3. Create a priority queue (pq) to store the time it takes to visit a node. Initialize it with node k and time 0.
  4. Iterate through the priority queue while it's not empty: a. Pop the node with the smallest time from the priority queue. b. Check if the current time is greater than the distance for the current node; if true, continue to the next iteration. c. For each neighbor's node in the graph, compare the sum of the current time and travel time to reach the neighbor with the minimum distance for the neighbor in the dist array. If the new calculated time is less, update the dist array and push the neighbor with the new calculated time into the priority queue.
  5. After the loop is finished, find the maximum value in the dist array (ignoring the first value, which is a placeholder). If the maximum value is infinity, return -1, as not all nodes could receive the signal. Otherwise, return the maximum time.