OAmaster
— / 14已做

Implement a simplified version of a banking system. All operations have a timestamp parameter (stringified ms, range 1 to 10⁹, strictly increasing).

Level 1 — Account Creation, Deposit, Transfer

  • boolean createAccount(int timestamp, String accountId) — creates a new account. Returns true if successful, false if account already exists.
  • Optional<Integer> deposit(int timestamp, String accountId, int amount) — deposits given amount to specified account. Returns the balance after the operation. Returns Optional.empty() if account doesn't exist.
  • Optional<Integer> transfer(int timestamp, String sourceAccountId, String targetAccountId, int amount) — transfer amount from source to target. Returns balance of source after the transfer, or Optional.empty() if either account doesn't exist, source == target, or source has insufficient funds.

Level 2 — Top Spenders by Outgoing Transactions

  • List<String> topSpenders(int timestamp, int n) — return the top n accounts ordered by highest total money withdrawn from the account (outgoing transactions only — transfer source and pay count). If two have the same total, order lexicographically by account id. Format: "accountId(amount)".

Level 3 — Scheduled Payments with Cashback

  • Optional<String> pay(int timestamp, String accountId, int amount) — withdraw given amount. All withdraw transactions provide a 2% cashback — 2% of the withdrawn amount (rounded down) will be refunded to the account 24 hours after the withdrawal. If the withdrawal is successful (i.e., the account has sufficient funds to perform the given amount), returns a unique payment identifier "payment{ordinal}" (e.g. "payment1", "payment2", etc.). Additional conditions:

  • Returns Optional.empty() if the account doesn't exist.

  • Returns Optional.empty() if the account has insufficient funds.

  • topSpenders should now also account for total amount of money withdrawn from accounts via pay.

  • The waiting period for cashback is 24 hours, equal to 24 * 60 * 60 * 1000 = 86,400,000 ms.

  • When it's time to process cashback for a withdrawal, the amount must be refunded to the account before any other transactions are performed at the relevant timestamp.

  • Optional<String> getPaymentStatus(int timestamp, String accountId, String paymentId) — return the payment status. Returns Optional.empty() if the account doesn't exist, or the payment doesn't exist for the specified account. Otherwise return string representing the payment status: "IN_PROGRESS" or "CASHBACK_RECEIVED".

Level 4 — Account Merging with History

  • boolean mergeAccounts(int timestamp, String accountId1, String accountId2) — merge accountId2 into accountId1. Returns false if accountId1 == accountId2 or any account doesn't exist. Returns true if accounts were successfully merged. Specifically:

  • All pending cashback refunds for accountId2 should still be processed, but refunded to accountId1 instead.

  • After the merge, it must be possible to check the status of payment identifiers belonging to accountId2 by replacing accountId2 with accountId1.

  • The balance of accountId2 should be added to the balance for accountId1.

  • topSpenders should recognize merged accounts — total outgoing transactions for merged accounts should be the sum of all money transferred and/or withdrawn in both accounts.

  • accountId2 should be removed from the system after the merge.

  • Optional<Integer> getBalance(int timestamp, String accountId, int timeAt) — return the total amount of money in the account at the given timestamp timeAt. If the specified account did not exist at a given time timeAt, returns Optional.empty().

  • If queries have been processed at timestamp timeAt, getBalance must reflect the account balance after the query has been processed.

  • If the account was merged into another account, the merged account should inherit its balance history.

解法

单个 Bank 类,由以下部分组成:

  • accounts: aid -> { balance, outgoing, history } —— history 是供 getBalance 使用的只追加 (timestamp, balance) 轨迹。
  • payments: paymentId -> { account, amount, cashback_ts, status } 以及按 (cashback_ts, paymentId) 排序的 cashback_heap。每个公共操作开头调用 _flush_cashback(now),弹出到期项并把 2% 返现(用 amount // 50 向下取整)入账到(可能已合并的)目标账户。
  • merged_to: a2 -> a1 用并查集风格解析 mergeAccounts 后的账户。所有账户查找都经过 _resolve_account(aid) 追链。
  • getBalancehistory 时间戳上 bisect_right 返回 timeAt 时的余额。

单次操作 O(log H)(历史二分)或 O(log C)(堆推/弹);topSpendersO(A log A)mergeAccounts 合并历史 O(H1 + H2)

import heapq
import bisect
from typing import Optional, List

class Bank:
    DAY_MS = 24 * 60 * 60 * 1000

    def __init__(self):
        self.accounts = {}
        self.payments = {}
        self.payment_counter = 0
        self.cashback_heap = []
        self.merged_to = {}

    def _resolve_account(self, aid):
        while aid in self.merged_to:
            aid = self.merged_to[aid]
        return aid

    def _flush_cashback(self, ts):
        while self.cashback_heap and self.cashback_heap[0][0] <= ts:
            refund_ts, pid = heapq.heappop(self.cashback_heap)
            pay = self.payments[pid]
            if pay["status"] == "CASHBACK_RECEIVED": continue
            aid = self._resolve_account(pay["account"])
            if aid not in self.accounts: continue
            refund = pay["amount"] // 50
            acc = self.accounts[aid]
            acc["balance"] += refund
            acc["history"].append((refund_ts, acc["balance"]))
            pay["status"] = "CASHBACK_RECEIVED"

    def createAccount(self, ts, aid) -> bool:
        self._flush_cashback(ts)
        if aid in self.accounts: return False
        self.accounts[aid] = {"balance": 0, "outgoing": 0, "history": [(ts, 0)]}
        return True

    def deposit(self, ts, aid, amount) -> Optional[int]:
        self._flush_cashback(ts)
        aid = self._resolve_account(aid)
        if aid not in self.accounts: return None
        acc = self.accounts[aid]
        acc["balance"] += amount
        acc["history"].append((ts, acc["balance"]))
        return acc["balance"]

    def transfer(self, ts, src, dst, amount) -> Optional[int]:
        self._flush_cashback(ts)
        src = self._resolve_account(src); dst = self._resolve_account(dst)
        if src == dst or src not in self.accounts or dst not in self.accounts: return None
        sa = self.accounts[src]
        if sa["balance"] < amount: return None
        sa["balance"] -= amount; sa["outgoing"] += amount
        self.accounts[dst]["balance"] += amount
        sa["history"].append((ts, sa["balance"]))
        self.accounts[dst]["history"].append((ts, self.accounts[dst]["balance"]))
        return sa["balance"]

    def topSpenders(self, ts, n) -> List[str]:
        self._flush_cashback(ts)
        items = sorted(
            ((aid, acc["outgoing"]) for aid, acc in self.accounts.items()),
            key=lambda x: (-x[1], x[0])
        )
        return [f"{aid}({amt})" for aid, amt in items[:n]]

    def pay(self, ts, aid, amount) -> Optional[str]:
        self._flush_cashback(ts)
        aid = self._resolve_account(aid)
        if aid not in self.accounts: return None
        acc = self.accounts[aid]
        if acc["balance"] < amount: return None
        acc["balance"] -= amount; acc["outgoing"] += amount
        acc["history"].append((ts, acc["balance"]))
        self.payment_counter += 1
        pid = f"payment{self.payment_counter}"
        cashback_ts = ts + self.DAY_MS
        self.payments[pid] = {"account": aid, "amount": amount, "cashback_ts": cashback_ts, "status": "IN_PROGRESS"}
        heapq.heappush(self.cashback_heap, (cashback_ts, pid))
        return pid

    def getPaymentStatus(self, ts, aid, pid) -> Optional[str]:
        self._flush_cashback(ts)
        aid = self._resolve_account(aid)
        if aid not in self.accounts or pid not in self.payments: return None
        if self._resolve_account(self.payments[pid]["account"]) != aid: return None
        return self.payments[pid]["status"]

    def mergeAccounts(self, ts, a1, a2) -> bool:
        self._flush_cashback(ts)
        a1 = self._resolve_account(a1); a2 = self._resolve_account(a2)
        if a1 == a2 or a1 not in self.accounts or a2 not in self.accounts: return False
        acc1 = self.accounts[a1]; acc2 = self.accounts[a2]
        acc1["balance"] += acc2["balance"]
        acc1["outgoing"] += acc2["outgoing"]
        merged_hist = sorted(acc1["history"] + acc2["history"], key=lambda x: x[0])
        clean = []
        for tts, bal in merged_hist:
            if clean and clean[-1][0] == tts:
                clean[-1] = (tts, bal)
            else:
                clean.append((tts, bal))
        acc1["history"] = clean
        acc1["history"].append((ts, acc1["balance"]))
        self.merged_to[a2] = a1
        del self.accounts[a2]
        return True

    def getBalance(self, ts, aid, time_at) -> Optional[int]:
        self._flush_cashback(ts)
        aid = self._resolve_account(aid)
        if aid not in self.accounts: return None
        hist = self.accounts[aid]["history"]
        keys = [h[0] for h in hist]
        idx = bisect.bisect_right(keys, time_at) - 1
        if idx < 0: return None
        return hist[idx][1]
import java.util.*;

class Bank {
    static final long DAY_MS = 24L * 60 * 60 * 1000;

    static class Account {
        long balance = 0, outgoing = 0;
        List<long[]> history = new ArrayList<>(); // (ts, balance)
    }

    static class Payment {
        String account; long amount; long cashbackTs; String status; // "IN_PROGRESS" / "CASHBACK_RECEIVED"
    }

    Map<String, Account> accounts = new HashMap<>();
    Map<String, Payment> payments = new HashMap<>();
    Map<String, String> mergedTo = new HashMap<>();
    PriorityQueue<long[]> cashbackHeap = new PriorityQueue<>((a, b) -> Long.compare(a[0], b[0]));
    Map<Long, String> heapPid = new HashMap<>(); // simple: store pid via cashbackHeap entry's second field
    int paymentCounter = 0;

    String resolve(String aid) {
        while (mergedTo.containsKey(aid)) aid = mergedTo.get(aid);
        return aid;
    }

    void flushCashback(long ts) {
        while (!cashbackHeap.isEmpty() && cashbackHeap.peek()[0] <= ts) {
            long[] top = cashbackHeap.poll();
            long refundTs = top[0];
            String pid = "payment" + top[1];
            Payment pay = payments.get(pid);
            if (pay == null || "CASHBACK_RECEIVED".equals(pay.status)) continue;
            String aid = resolve(pay.account);
            Account acc = accounts.get(aid);
            if (acc == null) continue;
            long refund = pay.amount / 50;
            acc.balance += refund;
            acc.history.add(new long[]{refundTs, acc.balance});
            pay.status = "CASHBACK_RECEIVED";
        }
    }

    public boolean createAccount(long ts, String aid) {
        flushCashback(ts);
        if (accounts.containsKey(aid)) return false;
        Account a = new Account();
        a.history.add(new long[]{ts, 0});
        accounts.put(aid, a);
        return true;
    }

    public Optional<Long> deposit(long ts, String aid, long amount) {
        flushCashback(ts);
        aid = resolve(aid);
        Account a = accounts.get(aid);
        if (a == null) return Optional.empty();
        a.balance += amount;
        a.history.add(new long[]{ts, a.balance});
        return Optional.of(a.balance);
    }

    public Optional<Long> transfer(long ts, String src, String dst, long amount) {
        flushCashback(ts);
        src = resolve(src); dst = resolve(dst);
        if (src.equals(dst)) return Optional.empty();
        Account sa = accounts.get(src), da = accounts.get(dst);
        if (sa == null || da == null || sa.balance < amount) return Optional.empty();
        sa.balance -= amount; sa.outgoing += amount;
        da.balance += amount;
        sa.history.add(new long[]{ts, sa.balance});
        da.history.add(new long[]{ts, da.balance});
        return Optional.of(sa.balance);
    }

    public List<String> topSpenders(long ts, int n) {
        flushCashback(ts);
        List<Map.Entry<String, Account>> list = new ArrayList<>(accounts.entrySet());
        list.sort((x, y) -> {
            if (x.getValue().outgoing != y.getValue().outgoing) return Long.compare(y.getValue().outgoing, x.getValue().outgoing);
            return x.getKey().compareTo(y.getKey());
        });
        List<String> out = new ArrayList<>();
        for (int i = 0; i < Math.min(n, list.size()); i++)
            out.add(list.get(i).getKey() + "(" + list.get(i).getValue().outgoing + ")");
        return out;
    }

    public Optional<String> pay(long ts, String aid, long amount) {
        flushCashback(ts);
        aid = resolve(aid);
        Account a = accounts.get(aid);
        if (a == null || a.balance < amount) return Optional.empty();
        a.balance -= amount; a.outgoing += amount;
        a.history.add(new long[]{ts, a.balance});
        paymentCounter++;
        String pid = "payment" + paymentCounter;
        Payment p = new Payment();
        p.account = aid; p.amount = amount; p.cashbackTs = ts + DAY_MS; p.status = "IN_PROGRESS";
        payments.put(pid, p);
        cashbackHeap.offer(new long[]{p.cashbackTs, paymentCounter});
        return Optional.of(pid);
    }

    public Optional<String> getPaymentStatus(long ts, String aid, String pid) {
        flushCashback(ts);
        aid = resolve(aid);
        if (!accounts.containsKey(aid)) return Optional.empty();
        Payment p = payments.get(pid);
        if (p == null) return Optional.empty();
        if (!resolve(p.account).equals(aid)) return Optional.empty();
        return Optional.of(p.status);
    }

    public boolean mergeAccounts(long ts, String a1, String a2) {
        flushCashback(ts);
        a1 = resolve(a1); a2 = resolve(a2);
        if (a1.equals(a2)) return false;
        Account x = accounts.get(a1), y = accounts.get(a2);
        if (x == null || y == null) return false;
        x.balance += y.balance;
        x.outgoing += y.outgoing;
        List<long[]> merged = new ArrayList<>(x.history.size() + y.history.size());
        merged.addAll(x.history); merged.addAll(y.history);
        merged.sort((p, q) -> Long.compare(p[0], q[0]));
        List<long[]> clean = new ArrayList<>();
        for (long[] h : merged) {
            if (!clean.isEmpty() && clean.get(clean.size() - 1)[0] == h[0]) clean.set(clean.size() - 1, h);
            else clean.add(h);
        }
        clean.add(new long[]{ts, x.balance});
        x.history = clean;
        mergedTo.put(a2, a1);
        accounts.remove(a2);
        return true;
    }

    public Optional<Long> getBalance(long ts, String aid, long timeAt) {
        flushCashback(ts);
        aid = resolve(aid);
        Account a = accounts.get(aid);
        if (a == null) return Optional.empty();
        int lo = 0, hi = a.history.size();
        while (lo < hi) {
            int mid = (lo + hi) >>> 1;
            if (a.history.get(mid)[0] <= timeAt) lo = mid + 1; else hi = mid;
        }
        if (lo == 0) return Optional.empty();
        return Optional.of(a.history.get(lo - 1)[1]);
    }
}
#include <bits/stdc++.h>
using namespace std;

class Bank {
    static constexpr long long DAY_MS = 24LL * 60 * 60 * 1000;

    struct Account {
        long long balance = 0, outgoing = 0;
        vector<pair<long long, long long>> history; // (ts, balance)
    };
    struct Payment {
        string account; long long amount, cashbackTs; string status;
    };

    unordered_map<string, Account> accounts;
    unordered_map<string, Payment> payments;
    unordered_map<string, string> mergedTo;
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<>> cashbackHeap;
    int paymentCounter = 0;

    string resolve(string aid) {
        while (mergedTo.count(aid)) aid = mergedTo[aid];
        return aid;
    }

    void flushCashback(long long ts) {
        while (!cashbackHeap.empty() && cashbackHeap.top().first <= ts) {
            auto [refundTs, n] = cashbackHeap.top(); cashbackHeap.pop();
            string pid = "payment" + to_string(n);
            auto it = payments.find(pid);
            if (it == payments.end() || it->second.status == "CASHBACK_RECEIVED") continue;
            string aid = resolve(it->second.account);
            auto ait = accounts.find(aid);
            if (ait == accounts.end()) continue;
            long long refund = it->second.amount / 50;
            ait->second.balance += refund;
            ait->second.history.push_back({refundTs, ait->second.balance});
            it->second.status = "CASHBACK_RECEIVED";
        }
    }

public:
    bool createAccount(long long ts, string aid) {
        flushCashback(ts);
        if (accounts.count(aid)) return false;
        Account a; a.history.push_back({ts, 0});
        accounts[aid] = move(a);
        return true;
    }

    optional<long long> deposit(long long ts, string aid, long long amount) {
        flushCashback(ts);
        aid = resolve(aid);
        auto it = accounts.find(aid);
        if (it == accounts.end()) return nullopt;
        it->second.balance += amount;
        it->second.history.push_back({ts, it->second.balance});
        return it->second.balance;
    }

    optional<long long> transfer(long long ts, string src, string dst, long long amount) {
        flushCashback(ts);
        src = resolve(src); dst = resolve(dst);
        if (src == dst) return nullopt;
        auto si = accounts.find(src), di = accounts.find(dst);
        if (si == accounts.end() || di == accounts.end() || si->second.balance < amount) return nullopt;
        si->second.balance -= amount; si->second.outgoing += amount;
        di->second.balance += amount;
        si->second.history.push_back({ts, si->second.balance});
        di->second.history.push_back({ts, di->second.balance});
        return si->second.balance;
    }

    vector<string> topSpenders(long long ts, int n) {
        flushCashback(ts);
        vector<pair<string, long long>> v;
        for (auto& [k, a] : accounts) v.push_back({k, a.outgoing});
        sort(v.begin(), v.end(), [](auto& a, auto& b) {
            if (a.second != b.second) return a.second > b.second;
            return a.first < b.first;
        });
        vector<string> out;
        for (int i = 0; i < min((int)v.size(), n); i++)
            out.push_back(v[i].first + "(" + to_string(v[i].second) + ")");
        return out;
    }

    optional<string> pay(long long ts, string aid, long long amount) {
        flushCashback(ts);
        aid = resolve(aid);
        auto it = accounts.find(aid);
        if (it == accounts.end() || it->second.balance < amount) return nullopt;
        it->second.balance -= amount; it->second.outgoing += amount;
        it->second.history.push_back({ts, it->second.balance});
        paymentCounter++;
        string pid = "payment" + to_string(paymentCounter);
        Payment p{aid, amount, ts + DAY_MS, "IN_PROGRESS"};
        payments[pid] = p;
        cashbackHeap.push({p.cashbackTs, paymentCounter});
        return pid;
    }

    optional<string> getPaymentStatus(long long ts, string aid, string pid) {
        flushCashback(ts);
        aid = resolve(aid);
        if (!accounts.count(aid)) return nullopt;
        auto it = payments.find(pid);
        if (it == payments.end()) return nullopt;
        if (resolve(it->second.account) != aid) return nullopt;
        return it->second.status;
    }

    bool mergeAccounts(long long ts, string a1, string a2) {
        flushCashback(ts);
        a1 = resolve(a1); a2 = resolve(a2);
        if (a1 == a2) return false;
        auto xi = accounts.find(a1), yi = accounts.find(a2);
        if (xi == accounts.end() || yi == accounts.end()) return false;
        xi->second.balance += yi->second.balance;
        xi->second.outgoing += yi->second.outgoing;
        vector<pair<long long, long long>> merged = xi->second.history;
        merged.insert(merged.end(), yi->second.history.begin(), yi->second.history.end());
        sort(merged.begin(), merged.end(), [](auto& a, auto& b) { return a.first < b.first; });
        vector<pair<long long, long long>> clean;
        for (auto& h : merged) {
            if (!clean.empty() && clean.back().first == h.first) clean.back() = h;
            else clean.push_back(h);
        }
        clean.push_back({ts, xi->second.balance});
        xi->second.history = clean;
        mergedTo[a2] = a1;
        accounts.erase(yi);
        return true;
    }

    optional<long long> getBalance(long long ts, string aid, long long timeAt) {
        flushCashback(ts);
        aid = resolve(aid);
        auto it = accounts.find(aid);
        if (it == accounts.end()) return nullopt;
        auto& h = it->second.history;
        int lo = 0, hi = h.size();
        while (lo < hi) {
            int mid = (lo + hi) >> 1;
            if (h[mid].first <= timeAt) lo = mid + 1; else hi = mid;
        }
        if (lo == 0) return nullopt;
        return h[lo - 1].second;
    }
};

NOTE - See the Problem Source section below for the original problem prompt Many years agooo, you decided to go fishing at the local pond, a place teeming with fish of all different sizes. You brought along a collection of baits, knowing that each one must be just the right size—strictly smaller than the fish—for the fish to bite. Each bait was special, capable of being used up to three times before it was no longer useful. Your goal was to catch as many fish as possible, but once a fish was caught, it would disappear from the pond, never to be seen again. The pond was a tricky place, and to catch the most fish, you knew you had to start with the biggest bait and work your way down, trying to hook the largest fish remaining each time, until your bait was either used up or not small enough to catch anything. With your strategy in mind, you embarked on this fishing adventure, aiming to see just how many fish you could haul from the pond before your baits were all used up.

Example 1

Input:

fishing = [1, 2, 3]
baitsss = [1]

Output:

2

Explanation: With bait size baits[0] = 1, you can catch two fish from the pond: fish[2] = 3 and fish[1] = 2, since the bait size is strictly smaller than the size of these fish (1 < 3 and 1 < 2). However, the smallest fish, fish[0] = 1, cannot be caught using this bait since the bait size is not strictly smaller.

解法

把鱼按大小降序排序、bait 按大小降序排序,每个 bait 最多用 3 次。从最大 bait 开始,吃掉所有 size > bait 的鱼,最多吃 3 条(bait 用完)。然后下一 bait。复杂度 O((n + m) log)

from typing import List

def caught_fish(fishing: List[int], baitsss: List[int]) -> int:
    fish = sorted(fishing, reverse=True)
    baits = sorted(baitsss, reverse=True)
    count = 0
    i = 0
    for b in baits:
        used = 0
        while i < len(fish) and used < 3 and fish[i] > b:
            i += 1
            used += 1
            count += 1
    return count
import java.util.*;

class Solution {
    int caughtFish(int[] fishing, int[] baitsss) {
        Integer[] fish = Arrays.stream(fishing).boxed().toArray(Integer[]::new);
        Integer[] baits = Arrays.stream(baitsss).boxed().toArray(Integer[]::new);
        Arrays.sort(fish, Collections.reverseOrder());
        Arrays.sort(baits, Collections.reverseOrder());
        int count = 0, i = 0;
        for (int b : baits) {
            int used = 0;
            while (i < fish.length && used < 3 && fish[i] > b) { i++; used++; count++; }
        }
        return count;
    }
}
class Solution {
public:
    int caughtFish(vector<int>& fishing, vector<int>& baitsss) {
        vector<int> fish = fishing, baits = baitsss;
        sort(fish.begin(), fish.end(), greater<int>());
        sort(baits.begin(), baits.end(), greater<int>());
        int count = 0, i = 0;
        for (int b : baits) {
            int used = 0;
            while (i < (int) fish.size() && used < 3 && fish[i] > b) { i++; used++; count++; }
        }
        return count;
    }
};

Feel free to checkout the image source at the bottom of the page for the original problem description :) Imagine you're a teacher with a list of student grade records, where each record is written in the format: "[name]: [grade]". Every student has received multiple grades, each ranging between 1 and 5. Your task is to figure out which student has performed the best overall, meaning you need to determine which one has the highest average grade. Each student has a unique average, so there's no tie to worry about. You'll need to carefully go through the records, calculate the averages, and then identify the top performer. You don’t have to stress about finding the fastest way to do it; as long as the method you use doesn't take too long, you'll be just fine!

Example 1

Input:

records = ["John: 5", "Michael: 4", "Ruby: 2", "Ruby: 5", "Michael: 5"]

Output:

"John"

Explanation: Let's calculate students' average grades:

  • "John" = 5
  • "Michael" = (4 + 5) / 2 = 4.5
  • "Ruby" = (2 + 5) / 2 = 3.5 Since 5 > 4.5 > 3.5, the result is "John".

Example 2

Input:

records = ["Kate: 5", "Kate: 5", "Maria: 2", "John: 5", "Michael: 4", "John: 4"]

Output:

"Kate"

Explanation: n/a

解法

dict[name] = (sum, count) 累计,最后找 sum / count 最大者。复杂度 O(n)

from typing import List

def coder_writing(records: List[str]) -> str:
    totals = {}
    for r in records:
        name, grade = r.split(":")
        name = name.strip(); g = int(grade.strip())
        s, c = totals.get(name, (0, 0))
        totals[name] = (s + g, c + 1)
    best_name = ""
    best_avg = -float("inf")
    for name, (s, c) in totals.items():
        avg = s / c
        if avg > best_avg:
            best_avg = avg
            best_name = name
    return best_name
import java.util.*;

class Solution {
    String coderWriting(String[] records) {
        Map<String, double[]> totals = new HashMap<>();
        for (String r : records) {
            String[] p = r.split(":");
            String name = p[0].trim();
            double g = Double.parseDouble(p[1].trim());
            double[] arr = totals.getOrDefault(name, new double[]{0, 0});
            arr[0] += g; arr[1]++;
            totals.put(name, arr);
        }
        String best = "";
        double bestAvg = -Double.MAX_VALUE;
        for (var e : totals.entrySet()) {
            double avg = e.getValue()[0] / e.getValue()[1];
            if (avg > bestAvg) { bestAvg = avg; best = e.getKey(); }
        }
        return best;
    }
}
class Solution {
public:
    string coderWriting(vector<string>& records) {
        unordered_map<string, pair<double, int>> totals;
        for (auto& r : records) {
            auto sp = r.find(':');
            string name = r.substr(0, sp);
            while (!name.empty() && name.back() == ' ') name.pop_back();
            double g = stod(r.substr(sp + 1));
            auto& a = totals[name];
            a.first += g; a.second++;
        }
        string best;
        double bestAvg = -1e18;
        for (auto& [name, p] : totals) {
            double avg = p.first / p.second;
            if (avg > bestAvg) { bestAvg = avg; best = name; }
        }
        return best;
    }
};

Checkout the source image below for the original problem statement :) Once upon a time, there was a mystical array filled with a collection of integers, known far and wide as "numbers." These numbers held a curious secret. For certain pairs of them, it was possible to rearrange or even leave the digits untouched to match one another, creating a unique bond. Your quest is to discover how many such distinct pairs exist within this enchanted array. Here's how the magic works: You must find pairs of numbers, where each pair consists of two indexes, i and j, such that i comes before j (i.e., 0 ≤ i < j < numbers.length). The twist? The number at position j can be transformed into the number at position i by swapping at most two of its digits. But here's an important note: sometimes, no swapping is needed at all! If the two numbers are already the same, they still count as a magical pair. Now, brave adventurer, your task is to complete the function named ziprecruiterCountDistinctSwappableDigitPairs, which will help you uncover the number of distinct pairs with these properties in the given array.

Constraints

  • 1 ≤ numbers.length ≤ 10^5
  • 0 ≤ numbers[i] ≤ 10^9
Pro解法 · 三语代码 · 复杂度分析
边界讨论 + 面试官追问 · $98 / 一年解锁

Checkout the image source below for the original problem statement :P Once upon a time, in the land of letters and words, there was a string called "sentence." This string was filled with words, and hidden among them were special words that contained a secret: within each of these words, one letter appeared at least three times. These magical "triple-letter" words held a unique charm, but they were hard to spot because the letters could be in any form, whether uppercase or lowercase. Your quest is to wander through the sentence and find all of these enchanted words, where the same letter appears at least three times, no matter its case. A word in this sentence is a sequence of English letters surrounded by white spaces, marking the boundaries of each word. You don’t need to rush to find the most efficient solution. As long as your method can explore each word carefully—checking the length of the sentence and the longest word within—it will be more than enough to solve the riddle within the limits of time. Go forth, and count all the special words hidden in the sentence!

Constraints

Unknwon for now

Example 1

Input:

sentence = "Dooddle moodle Pepper unsuccessfully"

Output:

3

Explanation: Checkout the image source below for the original problem statement :P Let’s dive into the magical realm of the sentence and explore each word together: First, we stumble upon the word "Doodle", and with a little inspection, we notice the letter "d" appears three times. This word is enchanted with a triple repeating letter! Next, we find the word "moodle." But alas, no letter appears three times, so this word doesn't hold the magic of triple repetition. Then comes "Pepper," where the letter "p" makes its presence known not once, not twice, but three times. Another enchanted word! Finally, we meet the word "unsuccessfully." This word is filled with magic, as two letters—"u" and "s"—each appear three times, making it twice as special. After our journey through the sentence, we’ve discovered three magical words that contain letters repeating at least three times. Therefore, the function should return 3, marking the count of these special words!

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

Feel free to checkout the image source below for the original problem statement In a world of numbers, a special kind of magic exists called the "cyclic shift." This mystical operation involves taking some digits from the end of a number and placing them at the beginning, while all the other digits move one step forward in perfect order. When performed correctly, this can transform one number into another. Now, imagine you are given two numbers, a and b, both with the same number of digits. These numbers are called "cyclic pairs" if, after performing a cyclic shift on a, it can become identical to b. You can shift none, some, or all the digits from the end of a to the front, and if it becomes equal to b, the pair is magical. Your quest is to take an array filled with positive integers and find how many such magical cyclic pairs exist. Specifically, you are tasked with counting all pairs i and j (where 0 ≤ i < j < a.length) such that the numbers a[i] and a[j] share the same number of digits, and one can become the other by performing a cyclic shift. How many of these hidden cyclic pairs will you discover on your journey through the array of numbers? The answer lies in your hands!

Constraints

  • 1 ≤ years.length ≤ 100
  • 1 ≤ years[i] ≤ 10⁴

Example 1

Input:

a = [13, 5604, 31, 2, 13, 4560, 546, 654, 456]

Output:

3

Explanation: Feel free to checkout the image source below for the original problem statement Once upon a time, there was a curious list of numbers: a = [13, 5604, 31, 2, 13, 4560, 546, 654, 456]. This list held a little secret—hidden within were pairs of numbers that could be transformed into each other through a magical process called cyclic shifting. Our clever heroes noticed that five pairs of numbers in the list could be perfectly matched through this shifting trick. For example, the number 13 could be shifted around in a circle, but it always remained the same as another 13! However, some numbers couldn't match no matter how much they shifted, like 546 and 456. Even though 654 was a magical twin to 546, 456 remained an outsider since it was too small to complete the shift. Another interesting case came when 4560 tried to make friends with 456, but alas, they were just too different—one had four digits, while the other had only three. And so, with the magic of cyclic shifts, the heroes discovered three perfect matches in this list!

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

Feel free to checkout the image source below for the original problem statement Once upon a time, there was an array of integers called "numbers," and the task was to divide these numbers between two special arrays, "first" and "second." However, the division wasn’t random—it followed a set of magical rules. The journey began with the very first number, numbers[0], which was gently placed into the first array. The second number, numbers[1], found its home in the second array. But for every number that followed, starting from numbers[2] and beyond, things became a bit more interesting. Each new number had to find the array where it would be happiest. How was that decided? Well, the number would go to the array that had more elements strictly greater than itself. It was drawn to where the bigger numbers lived! However, if both arrays had the same number of elements greater than the new number, it would choose the array that had fewer elements, preferring to balance things out. And if, after all of that, the arrays were still tied, the number would finally choose the first array as its home. Your quest is to complete the story by combining both arrays into one, with all the numbers from second gracefully appended to the end of first. This combined array will be your final answer. Now go forth and divide the numbers according to these magical rules, returning the grand combination of first and second!

Constraints

  • 2 ≤ numbers.length ≤ 10^5
  • 0 ≤ numbers[i] ≤ 10^9

Example 1

Input:

numbers = [5, 7, 6, 9, 2]

Output:

[5, 9, 2, 7, 6]

Explanation: NOTE: Part of the explanation is provided by Groot but not Ziprecruiter so be careful

  • numbers[0] = 5 goes to the first array and numbers[1] = 7 goes to the second array. At this point, first = [5] and second = [7]
  • Considering numbers[2] - 6:
  • There are 0 elements in the first array that are greater than numbers[2] = 6.
  • There is 1 element in the second array that is greater than numbers[2], so numbers[2] goes to the first array. Now, first = [5, 6] and second = [7].
  • For numbers[3] = 9, there are no elements greater than 9 in either array, but since both arrays are of equal length, numbers[3] goes to the first array. Now, first = [5, 6, 9] and second = [7].
  • Finally, numbers[4] = 2 goes to the first array as well, since there are no elements greater than 2 in either array and the lengths are equal. The final arrays are first = [5, 6, 9, 2] and second = [7]. The combined array is [5, 9, 2, 7, 6].
Pro解法 · 三语代码 · 复杂度分析
边界讨论 + 面试官追问 · $98 / 一年解锁

Feel free to checkout the image source at the bottom of the page for the original problem statement Imagine an exclusive event that everyone is eager to attend. The doors open at time 0, and people begin to arrive, each with their own special time of arrival, counted in seconds since the start of the event. But there’s a little twist — before anyone can step inside, they must go through a thorough ID check. This check takes exactly 5 minutes (or 300 seconds) per person. Now, here’s where things get tricky: if a person arrives and sees that there are already more than 10 people waiting in line for the ID check, they decide to leave immediately. They simply cannot bear the wait and head home without ever getting their ID checked. Your task is to determine the time each person will finish their ID check, starting from the time they arrived at the event. If someone leaves upon arrival because the queue is too long, their “processed” time will be the same as their arrival time — no ID check for them! Here are a few more things to keep in mind: The queue size is determined by how many people are waiting to begin their ID check. The person currently getting checked doesn’t count toward the queue. If multiple people arrive at exactly the same moment and the queue grows, the person who has fewer people ahead of them will be processed first, while the others will patiently wait their turn. Your goal is to return an array of integers where each number represents the exact moment in seconds when a person finishes their ID check — or if they left immediately, it’s simply their arrival time. Now, go ahead and figure out who gets into this exclusive event and when their ID checks are complete!

Constraints

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

Example 1

Input:

times = [4, 400, 450, 500]

Output:

[304, 700, 1000, 1300]

Explanation: Feel free to checkout the iamge source below for the original explanation :) In a bustling office, a series of events unfolded as people lined up for their ID checks: At the stroke of 4, the first visitor arrived. Since the office was empty, they were immediately ushered in for their ID check. The queue was a quiet, empty space. By 304, the first visitor had completed their ID check and left, leaving the queue just as serene as before. As the clock struck 400, the second visitor walked in. With no one in sight, they too started their ID check right away. The queue remained empty. When the third visitor arrived at 450, the office was still busy with the second visitor inside. So, they patiently took their place in the queue, now marked by a single name. Shortly after, at 500, the fourth visitor arrived. Noting the presence of one person already waiting, they joined the queue, which now held two names. At 700, the second visitor's ID check was completed, freeing up the office for the third visitor to step up. The queue now had just one name waiting. The clock struck 1000, and with the third visitor's check finished, the fourth visitor began theirs. The queue was now empty, with only the hum of activity left. By 1300, the fourth and final visitor finished their ID check, bringing an end to the day’s lineup of visitors.

Example 2

Input:

times = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

Output:

[301, 601, 901, 1201, 1501, 1801, 2101, 2401, 2701, 3001, 3301, 3601, 13, 14, 15]

Explanation: Feel free to checkout the iamge source below for the original explanation Once upon a time at a grand event, the first guest arrived at the stroke of 1 o’clock and began their ID check right away. Soon after, a wave of 11 more guests arrived, each one joining the queue behind the first guest. The queue grew longer with each new arrival, as they patiently waited their turn. However, as the queue stretched beyond 10 people, the last three guests took one look at the growing line and decided to leave. They felt overwhelmed by the number of people waiting and chose to forgo their ID checks, disappearing into the crowd instead. And so, the event continued with the queue still bustling with anticipation.

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

Feel free to check out the image source below for the original statement Imagine you’re organizing a grand, exclusive event that has everyone buzzing with excitement. The event kicks off at time 0, and guests start arriving at various times, measured in seconds since the event began. To attend, each guest must go through an ID check, which takes a precise 5 minutes (or 300 seconds) to complete. However, there’s a rule that adds a bit of drama: if a guest arrives and finds that there are already more than 10 people waiting in line for their ID check, they decide to leave right away, without going through the process. Your mission is to figure out when each guest will finish their ID check. If a guest leaves because the queue is too long, their completion time will be the same as their arrival time. Here’s how things work: The queue size is determined by how many people are waiting to start their ID check. The person currently being checked isn’t counted in this queue size. If a new guest arrives exactly when another person finishes their ID check, the guest who was waiting in line will be processed first. The new arrival will join the queue, waiting for their turn. Your task is to create a function named solution that takes an array of arrival times as input and returns an array where each entry shows when the guest’s ID check will be completed. If a guest leaves due to a long queue, their completion time should match their arrival time. Get ready to dive into the world of exclusive event management and determine who gets their ID checked and when!

Constraints

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

Example 1

Input:

times = [4, 400, 450, 500]

Output:

[304, 700, 1000, 1300]

Explanation: Feel free to check out the image source below for the original explanation In a bustling hall, the process of ID checks unfolded like a well-choreographed dance: At precisely 4 o’clock, the first guest arrived. With no one else waiting, they were swiftly ushered in to begin their ID check. The queue remained blissfully empty. By 304, the first guest had completed their check and departed, leaving the queue just as serene as before. As the clock struck 400, the second guest arrived. Seeing that the queue was still clear, they too began their ID check right away. The queue stayed empty. When the third guest arrived at 450, there was one person currently being checked. So, they patiently joined the queue, now marked with their name. The fourth guest arrived at 500 and noticed the queue had one person waiting. They added their name to the queue, which now held two. The scene shifted at 700, as the second guest’s ID check concluded. This allowed the third guest, who had been waiting, to step up and start their own ID check. The queue was now down to just one person. By 1000, the third guest finished their check, and the fourth guest took their turn. The queue had emptied once more. Finally, at 1300, the fourth and last guest completed their ID check, bringing the day’s events to a smooth and orderly end.

Example 2

Input:

times = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

Output:

[301, 601, 901, 1201, 1501, 1801, 2101, 2401, 2701, 3001, 3601, 13, 14, 15]

Explanation: Feel free to check out the image source below for the original explanation At the crack of 1 o’clock, the first guest arrived at the event and seamlessly began their ID check, setting the stage for what was to come. Soon after, a steady stream of 11 additional guests arrived, each one finding their place in the growing queue, eager to complete their own ID checks. However, as the queue stretched to more than 10 people, the last three guests arrived, glanced at the lengthy line, and decided to turn away. Seeing the daunting number of people waiting, they chose to leave, vanishing into the crowd as the others continued to wait their turn.

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

(no statement available)

Constraints

  • 1 ≤ playerDeckA.length ≤ 100
  • 1 ≤ playerDeckA[i] ≤ 10

Example 1

Input:

playerDeckA = [5]
playerDeckB = [2]

Output:

1

Explanation:

Example 2

Input:

playerDeckA = [1, 2]
playerDeckB = [3, 1]

Output:

6

Explanation: Unfortunately, we dont have access to the video explanation they provided..

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

Feel free to checkout the image source at the bottom of this page for the original problem description :) Imagine you're tasked with managing the guest list for an exclusive, high-profile event. The attendees are arriving, eager to get inside, but there’s a process they all must go through: an ID check. However, the entry point can only accommodate a limited number of people at a time, and each guest takes a different amount of time to verify, depending on their unique situation. Your challenge is to ensure that every guest is checked in efficiently, taking into account the capacity of the queue and the time each guest needs to get through. To solve this, you're designing a system where you must calculate the exact moment when the final guest will complete their ID check, making sure the process flows smoothly without unnecessary delays.

Example 1

Input:

lamps = [[1, 7], [5, 11], [7, 9]]
points = [7, 1, 5, 10, 9, 15]

Output:

[3, 1, 2, 1, 2, 0]

Explanation: n/a

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

You are given records in their current order. Each rec

Constraints

Record ids are unique.

Example 1

Input:

records = ["a|red","b|blue","c|green","d|yellow"]
queries = ["a","c","x"]

Output:

["None,b","b,d","None,None"]

Explanation: a has no previous id, c is between b and d, and x is not present.

Example 2

Input:

records = ["id7|one"]
queries = ["id7"]

Output:

["None,None"]

Explanation: A single record has no neighbors.

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

Feel free to checkout the image source at the bottom of the page for the original problem statement Imagine you’ve got a fantastic time machine at your disposal, and you’re on a grand journey through history. You’re given a list of years in which you must travel, starting from the year years[0]. Your adventure involves hopping from one year to the next in the sequence, and each leg of your journey has its own time cost: If you travel from one year to the exact same year, it takes you 0 hours (you’re already there!). If you move forward in time to a future year, it takes you 1 hour. If you journey backward to a past year, it takes you 2 hours. Your task is to calculate the total time required to complete your journey through all the years in the list, traveling in the given order. To sum up, you need to figure out how much time you’ll spend traveling between each pair of years, according to these rules. Your solution should be efficient enough to handle the task within the time constraints, even if it’s not the absolute fastest. So, set your time machine to work and calculate the total time for your historical adventure!

Constraints

  • 1 ≤ years.length ≤ 100
  • 1 ≤ years[i] ≤ 10⁴

Example 1

Input:

years = [2000, 1990, 2005, 2050]

Output:

4

Explanation: Imagine a time-travel adventure: First, you set off from the year 2000 and journey forward to 2021, a trip that takes you just 1 hour to traverse the years and witness the unfolding of the present. Then, you reverse course from 2021 back to 2005, a return journey that spans 2 hours, allowing you to revisit the past. In total, your time-travel adventure sums up to 3 hours, with each leg of the journey unfolding a different chapter of time.

Example 2

Input:

years = [2000, 2021, 2005]

Output:

3

Explanation: Feel free to checkout the image source at the bottom of the page for the original explanation Imagine a time-travel journey: First, you remain within the year 2021, a trip that requires no time at all, as you’re simply staying in the same year. Next, you embark on a journey from 2021 back to 2005. This trip takes you 2 hours to traverse the past. In total, your adventure through time takes 2 hours, with the first leg being instantaneous and the second a brief voyage through history.

Example 3

Input:

years = [2021, 2021, 2005]

Output:

2

Explanation: Feel free to checkout the image source at the bottom of the page for the original explanation First, you go from 2021 to 2021, which requires 0 hour as the trip takes plaxce within the smae year. Then you go from 2021 to 2005, which requires 2 hours. In total, you need 0 + 2 = 2 hours.

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

<img src = /Users/Eric/Deskto

Constraints

1 ≤ s.length ≤ 1000

Example 1

Input:

string = "abcdaaae"

Output:

3

Explanation: Pls see the source image posted in the Problem Source section below for detailed explanation.. Thank you so much for your understanding!

Example 2

Input:

string = "abacaba"

Output:

2

Explanation: Pls see the source image posted in the Problem Source section below for detailed explanation.. Thank you so much for your understanding!

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

解锁全部 11 道题的解法

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

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

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