OAmaster
— / 8已做

Implement a simple cloud storage system. All operations should be supported as listed below. The task consists of several levels; subsequent levels are opened when the current level is correctly solved. The system should be in-memory; you don't need to work with the real filesystem.

It is guaranteed that the given queries will never call operations that result in collisions between file and directory names.

Level 1 — Basic File Manipulation

  • boolean addFile(String name, int capacity) — add a new file name to the storage. capacity is its size in bytes. The current operation fails if a file with the same name already exists. Returns true if added successfully or false otherwise.
  • Optional<Integer> getFileSize(String name) — return the size of the file if it exists, or Optional.empty() otherwise.
  • Optional<Integer> deleteFile(String name) — delete the file. Returns the deleted file's size if successful, or Optional.empty() if the file does not exist.

Level 2 — Prefix Queries

  • List<String> getNFilesByPrefix(String prefix, int n) — return the list of strings representing names of the top n largest files with names starting with prefix, in the format "name1(size1)", "name2(size2)", ...". Sorted by size descending; tie broken by name ascending. Empty list if no match; fewer than n matches just returns all of them.

Level 3 — Multi-User with Capacity Limits

  • boolean addUser(String userId, int capacity) — add a new user. Fails if userId exists.
  • Optional<Integer> addFileBy(String userId, String name, int size) — like addFile but checks user's remaining quota. Returns new remaining capacity on success.
  • Optional<Integer> mergeUser(String userId1, String userId2) — merge user2 into user1: user2's files become owned by user1, user1's capacity gains user2's remaining capacity. Returns user1's new total capacity. Optional.empty() if either missing or ids equal.

All Level 1 addFile calls are made by user "admin" who has unlimited storage.

Level 4 — Backup and Restore

  • Optional<Integer> backupUser(String userId) — snapshot all files owned by userId (names + sizes) on a separate store, isolated from later mutations. Overwrites previous backup. Returns the number of backed-up files.
  • Optional<Integer> restoreUser(String userId) — restore the latest backup. If no backup exists, all of userId's files are deleted. Files whose name was taken by another user after backup are skipped. Returns the number of successfully restored files. mergeUser does not affect userId1's backup; userId2's backup is deleted along with the user.

解法

分四级设计:

  • Level 1:files: name → (size, owner),默认 owner 是 admin。
  • Level 2:线性扫 files 按前缀过滤,按 (-size, name) 排序取前 n
  • Level 3:users: id → (capacity, used)addFileBy 检查剩余配额;mergeUser 把 user2 的文件归到 user1,配额相加,再删除 user2。
  • Level 4:快照字典 backup: userId → {name: size}restoreUser 先删该用户当前文件,再回放备份,遇到被别的用户占用的文件名跳过。

复杂度:addFile / getFileSize / deleteFile / addFileByO(1)getNFilesByPrefixO(F + matched · log matched)mergeUserO(F)backupUser / restoreUserO(F)

class CloudStorage:
    ADMIN = "admin"

    def __init__(self):
        self.files = {}
        self.users = {self.ADMIN: {"cap": float('inf'), "used": 0}}
        self.backups = {}

    def addFile(self, name, capacity):
        if name in self.files:
            return False
        self.files[name] = {"size": capacity, "owner": self.ADMIN}
        self.users[self.ADMIN]["used"] += capacity
        return True

    def getFileSize(self, name):
        return self.files[name]["size"] if name in self.files else None

    def deleteFile(self, name):
        if name not in self.files:
            return None
        size = self.files[name]["size"]
        owner = self.files[name]["owner"]
        self.users[owner]["used"] -= size
        del self.files[name]
        return size

    def getNFilesByPrefix(self, prefix, n):
        matched = [(name, info["size"]) for name, info in self.files.items() if name.startswith(prefix)]
        matched.sort(key=lambda x: (-x[1], x[0]))
        return [f"{name}({size})" for name, size in matched[:n]]

    def addUser(self, userId, capacity):
        if userId in self.users:
            return False
        self.users[userId] = {"cap": capacity, "used": 0}
        return True

    def addFileBy(self, userId, name, size):
        if userId not in self.users or name in self.files:
            return None
        u = self.users[userId]
        if u["used"] + size > u["cap"]:
            return None
        self.files[name] = {"size": size, "owner": userId}
        u["used"] += size
        return u["cap"] - u["used"]

    def mergeUser(self, u1, u2):
        if u1 == u2 or u1 not in self.users or u2 not in self.users:
            return None
        for name, info in self.files.items():
            if info["owner"] == u2:
                info["owner"] = u1
        self.users[u1]["cap"] += self.users[u2]["cap"] - self.users[u2]["used"]
        self.users[u1]["used"] += self.users[u2]["used"]
        del self.users[u2]
        self.backups.pop(u2, None)
        return self.users[u1]["cap"]

    def backupUser(self, userId):
        if userId not in self.users:
            return None
        snap = {name: info["size"] for name, info in self.files.items() if info["owner"] == userId}
        self.backups[userId] = snap
        return len(snap)

    def restoreUser(self, userId):
        if userId not in self.users:
            return None
        to_del = [n for n, info in self.files.items() if info["owner"] == userId]
        for n in to_del:
            self.users[userId]["used"] -= self.files[n]["size"]
            del self.files[n]
        snap = self.backups.get(userId)
        if snap is None:
            return 0
        restored = 0
        u = self.users[userId]
        for n, size in snap.items():
            if n in self.files:
                continue
            if u["used"] + size > u["cap"]:
                continue
            self.files[n] = {"size": size, "owner": userId}
            u["used"] += size
            restored += 1
        return restored
import java.util.*;

class CloudStorage {
    static final String ADMIN = "admin";

    static class FileInfo { int size; String owner; FileInfo(int s, String o){ size=s; owner=o; } }
    static class User { long cap; long used; User(long c){ cap=c; used=0; } }

    Map<String, FileInfo> files = new HashMap<>();
    Map<String, User> users = new HashMap<>();
    Map<String, Map<String, Integer>> backups = new HashMap<>();

    CloudStorage() { users.put(ADMIN, new User(Long.MAX_VALUE)); }

    public boolean addFile(String name, int capacity) {
        if (files.containsKey(name)) return false;
        files.put(name, new FileInfo(capacity, ADMIN));
        users.get(ADMIN).used += capacity;
        return true;
    }
    public Optional<Integer> getFileSize(String name) {
        return files.containsKey(name) ? Optional.of(files.get(name).size) : Optional.empty();
    }
    public Optional<Integer> deleteFile(String name) {
        FileInfo f = files.remove(name);
        if (f == null) return Optional.empty();
        users.get(f.owner).used -= f.size;
        return Optional.of(f.size);
    }
    public List<String> getNFilesByPrefix(String prefix, int n) {
        List<Map.Entry<String, FileInfo>> matched = new ArrayList<>();
        for (var e : files.entrySet()) if (e.getKey().startsWith(prefix)) matched.add(e);
        matched.sort((a, b) -> a.getValue().size != b.getValue().size
                ? Integer.compare(b.getValue().size, a.getValue().size)
                : a.getKey().compareTo(b.getKey()));
        List<String> out = new ArrayList<>();
        for (int i = 0; i < Math.min(n, matched.size()); i++)
            out.add(matched.get(i).getKey() + "(" + matched.get(i).getValue().size + ")");
        return out;
    }
    public boolean addUser(String userId, int capacity) {
        if (users.containsKey(userId)) return false;
        users.put(userId, new User(capacity));
        return true;
    }
    public Optional<Long> addFileBy(String userId, String name, int size) {
        if (!users.containsKey(userId) || files.containsKey(name)) return Optional.empty();
        User u = users.get(userId);
        if (u.used + size > u.cap) return Optional.empty();
        files.put(name, new FileInfo(size, userId));
        u.used += size;
        return Optional.of(u.cap - u.used);
    }
    public Optional<Long> mergeUser(String u1, String u2) {
        if (u1.equals(u2) || !users.containsKey(u1) || !users.containsKey(u2)) return Optional.empty();
        for (FileInfo f : files.values()) if (f.owner.equals(u2)) f.owner = u1;
        users.get(u1).cap += users.get(u2).cap - users.get(u2).used;
        users.get(u1).used += users.get(u2).used;
        users.remove(u2);
        backups.remove(u2);
        return Optional.of(users.get(u1).cap);
    }
    public Optional<Integer> backupUser(String userId) {
        if (!users.containsKey(userId)) return Optional.empty();
        Map<String, Integer> snap = new HashMap<>();
        for (var e : files.entrySet())
            if (e.getValue().owner.equals(userId)) snap.put(e.getKey(), e.getValue().size);
        backups.put(userId, snap);
        return Optional.of(snap.size());
    }
    public Optional<Integer> restoreUser(String userId) {
        if (!users.containsKey(userId)) return Optional.empty();
        List<String> toDel = new ArrayList<>();
        for (var e : files.entrySet()) if (e.getValue().owner.equals(userId)) toDel.add(e.getKey());
        for (String n : toDel) { users.get(userId).used -= files.get(n).size; files.remove(n); }
        Map<String, Integer> snap = backups.get(userId);
        if (snap == null) return Optional.of(0);
        int restored = 0;
        User u = users.get(userId);
        for (var e : snap.entrySet()) {
            if (files.containsKey(e.getKey())) continue;
            if (u.used + e.getValue() > u.cap) continue;
            files.put(e.getKey(), new FileInfo(e.getValue(), userId));
            u.used += e.getValue();
            restored++;
        }
        return Optional.of(restored);
    }
}
#include <unordered_map>
#include <string>
#include <vector>
#include <optional>
#include <algorithm>
#include <climits>
using namespace std;

class CloudStorage {
    struct FileInfo { long long size; string owner; };
    struct User { long long cap; long long used; };
    unordered_map<string, FileInfo> files;
    unordered_map<string, User> users;
    unordered_map<string, unordered_map<string, long long>> backups;
    static constexpr long long INF = LLONG_MAX / 4;
public:
    CloudStorage() { users["admin"] = {INF, 0}; }

    bool addFile(const string& name, long long cap) {
        if (files.count(name)) return false;
        files[name] = {cap, "admin"};
        users["admin"].used += cap;
        return true;
    }
    optional<long long> getFileSize(const string& name) {
        auto it = files.find(name);
        return it == files.end() ? nullopt : optional<long long>(it->second.size);
    }
    optional<long long> deleteFile(const string& name) {
        auto it = files.find(name);
        if (it == files.end()) return nullopt;
        long long s = it->second.size;
        users[it->second.owner].used -= s;
        files.erase(it);
        return s;
    }
    vector<string> getNFilesByPrefix(const string& prefix, int n) {
        vector<pair<string, long long>> matched;
        for (auto& [k, v] : files)
            if (k.rfind(prefix, 0) == 0) matched.push_back({k, v.size});
        sort(matched.begin(), matched.end(), [](auto& a, auto& b){
            return a.second != b.second ? a.second > b.second : a.first < b.first;
        });
        vector<string> out;
        for (int i = 0; i < (int)min<size_t>(n, matched.size()); i++)
            out.push_back(matched[i].first + "(" + to_string(matched[i].second) + ")");
        return out;
    }
    bool addUser(const string& id, long long cap) {
        if (users.count(id)) return false;
        users[id] = {cap, 0};
        return true;
    }
    optional<long long> addFileBy(const string& id, const string& name, long long size) {
        if (!users.count(id) || files.count(name)) return nullopt;
        auto& u = users[id];
        if (u.used + size > u.cap) return nullopt;
        files[name] = {size, id};
        u.used += size;
        return u.cap - u.used;
    }
    optional<long long> mergeUser(const string& a, const string& b) {
        if (a == b || !users.count(a) || !users.count(b)) return nullopt;
        for (auto& [_, f] : files) if (f.owner == b) f.owner = a;
        users[a].cap += users[b].cap - users[b].used;
        users[a].used += users[b].used;
        users.erase(b);
        backups.erase(b);
        return users[a].cap;
    }
    optional<long long> backupUser(const string& id) {
        if (!users.count(id)) return nullopt;
        unordered_map<string, long long> snap;
        for (auto& [k, v] : files) if (v.owner == id) snap[k] = v.size;
        backups[id] = snap;
        return (long long)snap.size();
    }
    optional<long long> restoreUser(const string& id) {
        if (!users.count(id)) return nullopt;
        vector<string> del;
        for (auto& [k, v] : files) if (v.owner == id) del.push_back(k);
        for (auto& k : del) { users[id].used -= files[k].size; files.erase(k); }
        auto it = backups.find(id);
        if (it == backups.end()) return 0LL;
        long long restored = 0;
        auto& u = users[id];
        for (auto& [k, sz] : it->second) {
            if (files.count(k)) continue;
            if (u.used + sz > u.cap) continue;
            files[k] = {sz, id};
            u.used += sz;
            restored++;
        }
        return restored;
    }
};

In the expanse of a linear coordinate line, a celestial spectacle unfolds as numerous luminous orbs, each possessing its unique radiance, are strategically placed. The intricate details of these radiant spheres are cataloged within a two-dimensional array, dubbed "celestialArrangements." Each entry in this array encapsulates the essence of a single orb, revealing both its position and the extent of its luminosity. Within the realm of "celestialArrangements":

  • The ethereal coordinates of the ith orb are encapsulated in celestialArrangements[i][0].
  • Manifesting its brilliance, the positive radius of the ith orb's radiance is manifested through celestialArrangements[i][1]. As the night unfolds, each orb casts its enchanting glow, spanning from celestialArrangements[i][0] - celestialArrangements[i][1] to celestialArrangements[i][0] + celestialArrangements[i][1], inclusively. Yet, amidst this celestial ballet, a quest awaits. Adventurers must discern the mystical allure of those coordinates touched by the singular radiance of exactly one orb. For original prompt, pls refer to source images ˚₊‧꒰ა໒꒱ ‧₊˚

Constraints

  • 1 ≤ celestialArrangements.length ≤ 10^5
  • -10^9 ≤ celestialArrangements[i][0] ≤ 10^9
  • 1 ≤ celestialArrangements[i][1] ≤ 10^9

Example 1

Input:

lightSources = [[-2, 3], [2, 3], [2, 1]]

Output:

6

Explanation: For a set of luminous orbs with their respective radii, represented as [[-2, 3], [2, 3], [2, 1]], the resulting illumination yields 6 distinct sections. In the visual depiction, both overlapping and separate illuminated areas are observed, extending along the coordinate line from -6 to 6.

解法

扫描线:每盏灯产生区间 [c−r, c+r],每段端点事件 +1/-1。把所有事件按坐标排序,扫描时维护当前覆盖数 cnt;累加 cnt==1 段的总长度。注意坐标范围可能为负。时间 O(n log n)。

from typing import List

def count_single_coverage(light_sources: List[List[int]]) -> int:
    events = []
    for c, r in light_sources:
        events.append((c - r, 1))
        events.append((c + r + 1, -1))
    events.sort()
    cnt = 0
    total = 0
    prev = None
    for x, delta in events:
        if prev is not None and cnt == 1:
            total += x - prev
        cnt += delta
        prev = x
    return total
import java.util.*;

class Solution {
    public long countSingleCoverage(int[][] lightSources) {
        List<int[]> events = new ArrayList<>();
        for (int[] s : lightSources) {
            events.add(new int[]{s[0] - s[1], 1});
            events.add(new int[]{s[0] + s[1] + 1, -1});
        }
        events.sort((a, b) -> a[0] - b[0]);
        long total = 0;
        int cnt = 0;
        Integer prev = null;
        for (int[] e : events) {
            if (prev != null && cnt == 1) total += e[0] - prev;
            cnt += e[1];
            prev = e[0];
        }
        return total;
    }
}
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    long long countSingleCoverage(vector<vector<int>>& lightSources) {
        vector<pair<int, int>> events;
        for (auto& s : lightSources) {
            events.push_back({s[0] - s[1], 1});
            events.push_back({s[0] + s[1] + 1, -1});
        }
        sort(events.begin(), events.end());
        long long total = 0;
        int cnt = 0;
        bool first = true;
        int prev = 0;
        for (auto& [x, d] : events) {
            if (!first && cnt == 1) total += x - prev;
            cnt += d;
            prev = x;
            first = false;
        }
        return total;
    }
};

Let's delve into the art of crafting an algorithm , tailor-made for the exhilarating realm of currency trading. Picture a bustling marketplace where fortunes are won and lost with each passing day. Our algorithm, honed to perfection, is poised to navigate this volatile landscape with finesse. Our journey begins with two essential components: "prices" and "strategy." The former, a tapestry of daily currency prices, while the latter serves as our guiding light, indicating whether to buy, sell, or hold our precious assets. But here's where it gets intriguing. We're granted the power to tweak our strategy, to optimize our trading performance. How, you ask? By strategically selecting a range of consecutive days, precisely Mr."mrk" in length, and orchestrating a symphony of buying and selling within that span. Imagine it as a conductor wielding a baton, shaping the melody of our trades. The first half of our chosen range, we keep in a state of anticipation, a silent hold, while in the latter half, we unleash the power of our convictions, executing sell orders with precision. And what's our goal amidst this dance of numbers? It's simple yet profound: to maximize our total profit. We aim to strike a chord of prosperity, where the sum of our selling rates eclipses the sum of our buying rates, paving the way for wealth and prosperity. But remember, in this realm of uncertainty, where fortunes can shift in the blink of an eye, one must tread carefully. Yet armed with strategy and insight, we embark on this odyssey, ready to seize the opportunities that lie ahead. For original prompt, pls refer to source images ₍ᐢ. .ᐢ₎

Constraints

  • 1 ≤ prices.length ≤ 10^5
  • 1 ≤ prices[i] ≤ 10^4
  • strategy[i] ∈ {'B', 'S', 'H'}
  • 1 ≤ mrk ≤ prices.length,且 mrk 为偶数

解法

strategy 中 B=买、S=卖、H=持有。基础利润 = Σ (prices[i] if S else −prices[i] if B else 0)。允许选一个长度 mrk 的连续区间,前 mrk/2 天强制 H、后 mrk/2 天强制 S。求最大化新利润。对每个起点 i,新增 = − 原区间贡献 + 强制区间贡献。滑动窗口预计算每个长度 mrk 的区间的"基础贡献"和"被覆盖时新贡献"。时间 O(n)。

from typing import List

def earn_the_most(prices: List[int], strategy: List[str], mrk: int) -> int:
    n = len(prices)
    base = 0
    for i in range(n):
        if strategy[i] == 'S': base += prices[i]
        elif strategy[i] == 'B': base -= prices[i]

    # contribution if window [i, i+mrk-1] is replaced: first mrk/2 H, last mrk/2 S
    h = mrk // 2
    best = base
    for i in range(n - mrk + 1):
        old = 0
        for j in range(mrk):
            if strategy[i + j] == 'S': old += prices[i + j]
            elif strategy[i + j] == 'B': old -= prices[i + j]
        new = sum(prices[i + h: i + mrk])
        best = max(best, base - old + new)
    return best
import java.util.*;

class Solution {
    public long earnTheMost(int[] prices, char[] strategy, int mrk) {
        int n = prices.length;
        long base = 0;
        for (int i = 0; i < n; i++) {
            if (strategy[i] == 'S') base += prices[i];
            else if (strategy[i] == 'B') base -= prices[i];
        }
        int h = mrk / 2;
        long best = base;
        for (int i = 0; i + mrk <= n; i++) {
            long old = 0, neu = 0;
            for (int j = 0; j < mrk; j++) {
                if (strategy[i + j] == 'S') old += prices[i + j];
                else if (strategy[i + j] == 'B') old -= prices[i + j];
                if (j >= h) neu += prices[i + j];
            }
            best = Math.max(best, base - old + neu);
        }
        return best;
    }
}
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    long long earnTheMost(vector<int>& prices, string strategy, int mrk) {
        int n = prices.size();
        long long base = 0;
        for (int i = 0; i < n; i++) {
            if (strategy[i] == 'S') base += prices[i];
            else if (strategy[i] == 'B') base -= prices[i];
        }
        int h = mrk / 2;
        long long best = base;
        for (int i = 0; i + mrk <= n; i++) {
            long long old = 0, neu = 0;
            for (int j = 0; j < mrk; j++) {
                if (strategy[i + j] == 'S') old += prices[i + j];
                else if (strategy[i + j] == 'B') old -= prices[i + j];
                if (j >= h) neu += prices[i + j];
            }
            best = max(best, base - old + neu);
        }
        return best;
    }
};

Once upon a time, in a realm of integers, there was a quest to find the first spot where the landscape changed dramatically. The adventurers were given a map called "numbers," guiding them through this numerical landscape. Their mission was to discover the very first location where the terrain rose sharply, where three consecutive points, represented by "numbers[i]," "numbers[i + 1]," and "numbers[i + 2]," stood higher than a certain threshold. As they journeyed through this numerical expanse, they diligently searched for a place where the terrain shifted abruptly, where three consecutive points towered above the threshold. Should they find such a place, they would mark the index "i" and return triumphantly. Yet, if no such spot existed, they would sadly return with news of their quest's failure, marked by a return value of -1. Their journey was not about speed, but about thorough exploration. So long as their method did not exceed a complexity greater than O(numbers.length²), they could traverse the landscape within the allotted time. For original prompt, please refer to source image.

Example 1

Input:

buddyList = [0, 1, 4, 3, 2, 5]
target = 1

Output:

2

Explanation: At the starting point, index 0, the trio of companions (buddyList[0], buddyList[1], buddyList[2]) includes 0 and 1, neither of which surpasses the threshold of 1. Moving to index 1, the companionship of (buddyList[1], buddyList[2], buddyList[3]) comprises 1, 4, and 3. However, only 4 exceeds the target value. It's not until index 2 that the trio (buddyList[2], buddyList[3], buddyList[4]) emerges, featuring all friends whose values surpass the threshold. Thus, the answer lies at index 2, where the landscape shifts dramatically.

Pro解法 · 三语代码 · 复杂度分析
边界讨论 + 面试官追问 · $98 / 一年解锁

In the tale of two interconnected destinations served by flights, travelers aim to complete round trips between them. Flights in one direction take 100 minutes, and return flights take the same duration. Their goal is to determine the moment they'll finish their final round trip, assuming they always board the earliest available flight. To aid in their journey, the function "tDeskFlights" requires three inputs: two arrays of departure times (one for outbound flights and one for return flights) and the number of round trips planned. It then returns the time in minutes when the last round trip concludes. For original prompt, pls refer to source image ౨ৎ

Constraints

  • 1 ≤ c2d.length, d2c.length ≤ 10^5
  • 0 ≤ c2d[i], d2c[i] ≤ 10^9
  • 1 ≤ journies ≤ min(c2d.length, d2c.length)
  • c2dd2c 均按升序排列

Example 1

Input:

c2d = [0, 200, 500]
d2c = [99, 210, 450]
journies = 1

Output:

310

Explanation: Your journey begins as you depart from C to D at minute 0, arriving at D at 100. Shortly after, you return from D to C on the earliest available flight, departing D at 210. Thus, you reach C at 310, marking the conclusion of your journey.

Pro解法 · 三语代码 · 复杂度分析
边界讨论 + 面试官追问 · $98 / 一年解锁

Once upon a time, in a land filled with numbers, there was a group of friends called "friendsList." They were on a quest, guided by a positive number named "minimumPairs." Their mission was to count how many groups of adjacent friends there were, where at least "minimumPairs" of them shared the same characteristics. In other words, they needed to find out how many groups of friends walked together, where there were twice as many friends (each at different positions) who were just like each other, as required by the "minimumPairs" rule. After exploring their journey for a while, they came back with the total count of such groups, having completed their mission successfully. For original prompt, please refer to source image.

Constraints

  • 1 ≤ friendList.length ≤ 10^5
  • 0 ≤ friendList[i] ≤ 10^5
  • 1 ≤ minimumPairs ≤ 10^9

Example 1

Input:

friendList = [0, 1, 0, 1, 0]
minimumPairs = 2

Output:

3

Explanation: Three friend groups meet the criteria of having at least minimumPairs = 2 pairs of matching traits: The first group, consisting of friends 0, 1, 2, and 3, where friend 0 is alike friend 2, and friend 1 is alike friend 3. The second group, including friends 1, 2, 3, and 4, where friend 1 matches friend 3, and friend 2 matches friend 4. The third group, comprising friends 0 through 4, where friend 0 matches friend 2, friend 1 matches friend 3, and friend 2 matches friend 4. In each of these friend groups, there exists at least one pair of friends with the same traits.

Example 2

Input:

friendList = [2, 2, 2, 2, 2]
minimumPairs = 3

Output:

1

Explanation: Explanation not found.

Pro解法 · 三语代码 · 复杂度分析
边界讨论 + 面试官追问 · $98 / 一年解锁

In the bustling excitement of an event's beginning, attendees flow in at the timestamps given in moments (seconds since the doors opened). Each attendee needs a 300-second ID check, processed one at a time on a single counter; if the counter is idle when someone arrives, their check starts immediately, otherwise they queue. Return the time at which the last attendee finishes being checked.

Constraints

  • 1 ≤ moments.length ≤ 10^5
  • 0 ≤ moments[i] ≤ 10^9
  • moments 已按升序排列

Example 1

Input:

moments = [1, 6, 9, 502]

Output:

1201

Explanation: Explanation not found ꒰ঌ໒꒱

Pro解法 · 三语代码 · 复杂度分析
边界讨论 + 面试官追问 · $98 / 一年解锁

In the narrative of a sentence filled with words, your quest is to seek out those special words that hold a secret: they contain triple repeating letters, where the same letter appears at least three times consecutively. Each word in the sentence is a sequence of English letters bordered by whitespace characters. As you embark on this linguistic adventure, remember that letters are to be counted regardless of their case. Your task is not to find the most efficient solution, but one that explores the sentence with a time complexity no worse than O(sentence.length * longestWord.length), ensuring it fits within the constraints of time. The function narrativeWords awaits your guidance. It takes the sentence as input and returns the count of words harboring at least one letter that appears three times consecutively. For original prompt, pls refer to source images જ⁀

Constraints

  • 1 ≤ sentence.length ≤ 10^5
  • sentence 仅包含英文字母与空白字符

Example 1

Input:

words = "Dooddle moodle Pepper unsuccessfully"

Output:

3

Explanation: Let's examine each word within this sentence: "Dooddle" stands out as it contains a triple repeating letter, with "d" appearing three times. "Moodle," however, does not meet the criteria, lacking a letter repeated thrice. "Pepper" catches our attention with its triple repeating letter, "p" occurring three times. As for "unsuccessfully," it impressively boasts not just one, but two triple repeating letters, with both "u" and "s" making their triumphant appearances.

Pro解法 · 三语代码 · 复杂度分析
边界讨论 + 面试官追问 · $98 / 一年解锁
Pro 会员

解锁全部 5 道题的解法

题面你已经看到了 — 解法 + 三语代码 + 复杂度推导 + 边界讨论, Pro 解锁.

Pro 解锁全部
  • 📚1000+ 道真实北美 OA, Python / Java / C++ 三语题解
  • 📊个人 dashboard + 进度可视化 + 14 天活跃图
  • 📝题目笔记跨设备同步 + 个人复盘库
  • 🔓随时取消下次续费, Stripe Customer Portal 自助管理
$12/月($98/年, 一次付清省 32%)

≈ 北美 SWE 工资 10 分钟 · LeetCode Premium $35/月 的 23%