↓Skip to main content
  1. LeetCode/

LeetCode 3639: Minimum Time to Activate String

·3 mins· ·
LeetCode Medium Binary-Search Counting String
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2025-08-03

  • Submissions: Accepted (first try)

Approach
#

At each time step one position becomes *. Find the first time the number of substrings containing at least one * reaches k.

My approach: how many new valid substrings each star adds
#

When a star lands at idx, find the nearest star to its left, left, and to its right, right (use -1 and n if there is none).

The new valid substrings are exactly those that contain idx but no other star: start in (left, idx] and end in [idx, right), giving (idx - left) * (right - idx).

The first time the running total reaches k is the answer.

My Solution
#

import bisect

class Solution:
    def minTime(self, s: str, order: List[int], k: int) -> int:
        n = len(s)
        stars = [-1, n]                       # sorted star positions plus two sentinels
        total = 0
        for t, idx in enumerate(order):
            i = bisect.bisect_left(stars, idx)
            left, right = stars[i - 1], stars[i]
            total += (idx - left) * (right - idx)
            if total >= k:
                return t
            stars.insert(i, idx)
        return -1

My original code had a hand-written lower bound; this version uses bisect.

One concern: list.insert is O(n), so the worst case is O(n^2). In practice insert is a fast memory move and n = 10^5 passes, but in an interview it is better to offer something sturdier.

Sturdier: binary search on time
#

“Later time, more stars, more valid substrings”, so check(t) = “after placing the first t+1 stars, are there at least k valid substrings” is monotonic, and t can be binary searched.

check counts the complement: all n(n+1)/2 substrings minus the star-free ones. Star-free substrings come from each maximal star-free run; a run of length L contributes L(L+1)/2.

class Solution:
    def minTime(self, s: str, order: List[int], k: int) -> int:
        n = len(s)
        total = n * (n + 1) // 2
        if total < k:
            return -1

        def count(t: int) -> int:
            star = [False] * n
            for idx in order[:t + 1]:
                star[idx] = True
            bad = run = 0
            for is_star in star:
                run = 0 if is_star else run + 1
                bad += run                    # star-free substrings ending here
            return total - bad

        lo, hi = 0, n - 1
        while lo < hi:
            mid = (lo + hi) // 2
            if count(mid) >= k:
                hi = mid
            else:
                lo = mid + 1
        return lo

bad += run adds the run star-free substrings that end at the current position; summing gives all star-free substrings.

Complexity
#

ApproachTime
Insert stars one by oneworst O(n^2) (list.insert)
Binary search on timeO(n log n)

Mistakes to Avoid
#

  • Recounting all substrings after every star: O(n^2) or worse.
  • Not checking first whether k exceeds the total number of substrings: if even all stars cannot reach it, return -1.
  • Using (idx - left + 1) * (right - idx + 1): the neighboring stars themselves must not be included.

Interview Explanation
#

Each new star adds the substrings that contain it but no other star, which is the product of its distances to the nearest stars on each side, so I keep a sorted list of stars, find neighbors with bisect, and accumulate. Since insertion is O(n), a sturdier option is binary search on time: more stars means more valid substrings, and check subtracts the star-free substrings from the total in O(n), for O(n log n) overall.

Related

LeetCode 981: Time Based Key-Value Store
·2 mins
LeetCode Medium Hash-Table String Binary-Search Design
LeetCode 981 note: store a (timestamp, value) list per key, with timestamps increasing; get binary searches the last timestamp <= the query
LeetCode 2391: Minimum Amount of Time to Collect Garbage
·2 mins
LeetCode Medium Prefix-Sum String Array
LeetCode 2391 note: pickup time is the total garbage count; each truck only drives to the last house with its type, using a prefix sum of travel
LeetCode 3545: Minimum Deletions for At Most K Distinct Characters
·1 min
LeetCode Easy Greedy Hash-Table String Sorting Counting
LeetCode 3545 note: reducing the number of kinds means deleting whole kinds, starting from the least frequent
LeetCode 3541: Find Most Frequent Vowel and Consonant
·1 min
LeetCode Easy Hash-Table String Counting
LeetCode 3541 note: count characters, take the maximum among vowels and among consonants and add them; a missing class counts as 0
LeetCode 1410: HTML Entity Parser
·2 mins
LeetCode Medium Hash-Table String
LeetCode 1410 note: scan left to right, trying all six entities at each position and skipping past a match; chained replace does not work
LeetCode 3612: Process String with Special Operations I
·2 mins
LeetCode Medium String Simulation
LeetCode 3612 note: simulate the four operations with a list; put the “result is non-empty” check inside the * branch, or * gets appended as a letter