LeetCode Frequency 888 Spec
This book is a compact practice surface for LeetCode China interview preparation.
Typography and Math Contract
This book inherits the repository-wide book style contract in
BOOK_STYLE.md: all prose, headings, controls, tables, captions, and
ordinary UI text must default to PingFang. Code blocks, inline code, terminal
snippets, and code editors use the Cursor/LeetCode stack
Monaco, "Cascadia Code", Consolas, "Courier New", ui-monospace, SFMono-Regular, Menlo, monospace. Problem constraints, variables, arrays,
matrices, complexity, numeric bounds, and benchmark-style metrics should use
LaTeX/KaTeX whenever possible.
Data Contract
The target ranking starts from the LeetCode China problemset sorted by 出题频率 on May 16, 2026. The pinned daily-question row is excluded because it is not part of the frequency order. The source ranking target is Top 888.
The default problem list is deduplicated. Obvious duplicates are detected by a normalized Chinese title, such as the LCCI/LCR variant of the same canonical problem. The row with the higher frequency rank is kept, and the removed row is recorded in the duplicate audit section so it can be checked manually. The top rank shown on kept rows remains the original frequency rank, so removed rows leave intentional gaps.
Hot 100 membership comes from the public Hot 100 study plan. If a Hot 100 problem is outside the Top 888, it is appended without a Top 888 rank and keeps its frequency-order position for Hot 100 sorting.
ByteDance membership comes from the LeetCode China company favorite lists:
bytedance-all, bytedance-thirty-days, bytedance-three-months,
bytedance-six-months, and bytedance-more-than-six-months. The page mirrors
those five filters: all ByteDance, past 30 days, past 3 months, past 6 months,
and more than 6 months ago. The intended full ByteDance source has 1,503 rows
and is sorted by company frequency. Rows not already present in the Top 888 or
Hot 100 supplement are appended after those rows and keep their ByteDance rank.
ByteDance company data is generated by npm run sync:leetcode-bytedance.
LeetCode China gates company favorites behind the logged-in Plus session, so
the reproducible full sync accepts LEETCODE_CN_COOKIE. The script uses the
same favoriteQuestionList GraphQL operation that the company page uses,
paginates by skip and limit, and sorts with
{ sortField: "FREQUENCY", sortOrder: "DESCENDING" }. If no authenticated rows
are available, it writes a clearly marked legacy Top 888 fallback. The script
can also merge Top 100 bucket rows exported from the Chrome-rendered logged-in
company pages. Those rows are marked as official page Top100 and override the
corresponding all, past 30 days, past 3 months, past 6 months, or older-than-6
months rank; legacy rows remain marked as old data. The page must expose the
source of each bucket instead of pretending the 1,503-row company list is
complete.
LingShen membership comes from the 12 topic links in 灵茶山艾府’s “How to
practice scientifically” post: sliding window and two pointers, binary search,
monotonic stack, grid graphs, bit manipulation, graph algorithms, dynamic
programming, data structures, math, greedy/thinking, linked list/trees/
backtracking, and strings. The sync command is npm run sync:leetcode-lingshen.
It reads the original problem order, topic grouping, rating, and paid-only hint
from the LeetCode China discussion posts, then fills title, tags, statement
preview, approach preview, and generic study checks from LeetCode metadata and
local public Doocs material. LingShen problems not already present in Top 888,
ByteDance, or series supplements are appended as LingShen supplemental rows and
still participate in search, local state, opened practice panels, list flow,
and suggested flow.
Contest difficulty ratings are generated by
npm run sync:leetcode-contest-ratings from the public
zerotrac/leetcode_problem_rating dataset. The page merges those ratings into
the whole book rather than showing them only inside LingShen lists: the main
table has a dedicated rating column, and tag popovers, related-problem cards,
series/category member lists, and search indexes must all carry the same rating
fields. Problems with contest-source data keep the contest name, problem index,
and source label. Problems missing a zerotrac row may fall back to a LingShen
rating when available, with the fallback source preserved internally. Problems
with no rating source render --; the page must not fabricate estimated
ratings.
Official code templates are generated by a local sync script rather than by
cross-origin LeetCode requests from the GitHub Pages runtime. The command is
npm run sync:leetcode-templates. It prefers LeetCode China’s public GraphQL
question.codeSnippets field, then falls back to the matching official
LeetCode global template when the China endpoint is rate-limited or returns a
challenge page. The script can use LEETCODE_CN_COOKIE or LEETCODE_COOKIE for
an authenticated session and supports --missing-only so later runs merge
existing results and fetch only missing problems. The sync target is the
deduplicated book catalog, including ByteDance-only supplemental rows, so
supplements get the same official editor defaults as Top 888 rows. Results are
written to src/data/leetcode-code-templates.ts, and the page reads only that
static module.
ByteDance-only supplemental rows must not render generic placeholder study
text. If a ByteDance row is not already in the main problem dataset,
src/data/leetcode-bytedance.ts carries its local statement preview, topic
tags, approach preview, and generic study checks. Those fields come from the
public LeetCode problem content plus local study synthesis, while examples
remain omitted from the rendered local statement.
Official data ranges are generated by npm run sync:leetcode-constraints.
The script reads the same merged book rows that the page renders, extracts the
提示 / Constraints list from LeetCode China’s public problem statement,
and falls back to the matching public Doocs statement for paid-only questions
when the LeetCode API omits the content. Results are written to
src/data/leetcode-problem-constraints.ts. Every rendered problem row must
have nonempty data ranges. The local practice panel appends those ranges as one
compact inline constraints sentence at the end of the statement body, not as a
separate bordered block or bullet list. Because these constraints are mostly
mathematical expressions, inline constraint separators use spaced ASCII
semicolons in every locale; Chinese prose labels keep Chinese punctuation where
it reads naturally. Each constraint item’s own trailing period or semicolon is
trimmed before inline joining, so the rendered sentence never produces broken
punctuation such as 。 ;. Constraint text must use the same readable weight and
color as the statement body, not faint muted helper text. The statement and
constraint sentence use the same larger PingFang-first reading font and normal
visual weight. Questions whose official statement does not separate data ranges, such
as some database tasks, receive an explicit note to use the table schema or
input definition in the statement.
Statement and data-range math is generated by npm run sync:leetcode-math.
The script reads the same merged book rows, normalizes common LeetCode math
fragments, and writes KaTeX-rendered static HTML to
src/data/leetcode-problem-math.ts. Superscripts, subscripts, matrix or grid
dimensions, Big-O notation, numeric ranges, and comparison chains must render
as math instead of broken plain text such as n 2, m x n, or 10 9.
Obvious statement variables and programming identifiers such as n, height,
height[i], haystack, and needle should also render as inline math when
that improves readability; ordinary prose numbers stay as text unless they are
part of a formula or range. The page reads only the generated escaped HTML and
imports KaTeX CSS globally. Generated statement HTML and title hover previews
omit official example sections; examples remain data for the official
run-examples workflow, not prose inside the local statement. If an older
statementPreview is a truncated preview string, the generator must use a
local official-statement override so the rendered page never shows half
sentences, dangling parentheses, or flattened lists. npm run check:leetcode-math
must pass before publishing math or statement changes.
Official statement visuals are generated by
npm run sync:leetcode-statement-assets. The script reads the same merged
book rows, fetches LeetCode China’s official statement HTML, and stores
sanitized static snippets in src/data/leetcode-problem-assets.ts. The page
renders official images from the statement and schema-style tables that appear
before the example or constraints sections inside the opened practice
statement panel. Title hover previews remain text-only, and the page does not
make LeetCode API requests for statement-asset metadata at runtime.
Official related problems are also generated by a local sync script. The
command is npm run sync:leetcode-related. It reads LeetCode China’s public
GraphQL question.similarQuestions field for every Top 888, Hot 100, and
ByteDance supplemental row, then writes the static result to
src/data/leetcode-related.ts. The page does not make related-problem
requests at runtime. At build time it combines the official list with
same-series detection from local slugs, such as house-robber,
house-robber-ii, and house-robber-iii, plus a small same-track set derived
from shared topic tags and frequency rank.
Previously verified exact frequency percentages are preserved. New rows that
can be ordered by frequency but do not expose an exact percentage in the public
response are labeled with 约 or with their supplemental source, so exact and
estimated percentages are not confused.
Company follow-ups are separate from generated study checks. A company follow-up is included only when a public LeetCode Discuss interview post mentions the company, the problem or a close variant, and the follow-up prompt. Each included follow-up stores a concise answer, the company name, and the source link. If no public source was found for a problem, the page says so rather than assigning a company by inference.
Problem study content must explain the individual problem first, not merely
combine tag-level templates. approachPreview needs to name the problem’s own
state, invariant, boundaries, and correctness reason; when the key idea is a
compression from a simpler solution to the optimal one, such as dynamic
programming compressed into greedy boundaries, that compression must be stated.
followUps must be concrete variants or pitfalls that naturally belong to the
problem, with short answers usable in an interview. implementationReferences
must include at least one submit-ready primary solution; for high-frequency
problems that are easy to misunderstand, add a baseline solution, path
reconstruction, unreachable-case handling, or another reference that explains
the tradeoff behind the primary solution. Generic prompts such as boundary
cases, complexity, or space compression may supplement the entry, but they must
not replace problem-specific content.
Page Contract
The page does not show the global site header. The title area uses a compact workspace layout, and the large cover is not shown in the first viewport. Stats and secondary metadata live below the working list. The problem list is the primary workspace; on desktop, the first problem rows should be visible without scrolling. The table is sized to fit the content column without an internal horizontal scrollbar.
Each row shows the identifiers that matter for practice:
- the Top 888 frequency rank;
- the Hot 100 rank, sorted by frequency rather than by the study-plan order;
- the ByteDance company rank when the row is in the ByteDance company list;
- the original LeetCode frontend problem id inside the clickable title.
Approach, implementation, tags, and related controls are attached to the title cell so the pointer does not need to cross the table. Clicking the linked title still opens LeetCode directly, but hover/focus on that title must show the same warm yellow block popover used by the other previews, containing the local statement and compact data ranges. The statement is also shown inside the practice panel above the editor. Moving slightly right to Approach shows the approach. Moving slightly farther right to Implementation shows the reference implementation. Moving one more small step to Tags shows topic tags and supplemental badges. The Related preview shows same-series problems first, then official LeetCode related problems, then a compact same-track high frequency set. In-book related problems open directly in the local practice panel; the same-series section also offers a compact action that starts list flow for that series. Related problems outside the book open on LeetCode China and keep their paid-only marker when LeetCode reports one. These preview targets stay compact and must not increase the normal row height.
Hover details for the title, approach, implementation, tags, related problems,
suggested practice, shortcut help, and daily stats must use the page’s own warm
yellow block popovers. The page must not depend on browser-native title
tooltips or custom gray strip pseudo-tooltips. Text that used to live in a gray
strip, such as “hover to view; click or Enter/Space to pin”, belongs at the top
of the matching yellow popover. Plain controls without a yellow popover keep
only accessible aria-label text and the central shortcut list.
As an acceptance check, the rendered practice page DOM should not leave any
title attributes that would trigger browser-native gray tooltips.
All page-owned hover popovers must be hover-trackable by default. Even when
there is visual spacing between the trigger and the floating panel, a
transparent hit-testable bridge or an equivalent delayed-close mechanism must
connect them so moving the pointer downward or upward from the trigger into the
panel does not make the popover disappear. The open hover hit area includes the
trigger, the bridge, and the popover body; the popover may close only after the
pointer leaves all three. This applies to title, approach, implementation, tags,
related problems, category or series “Ideas”, suggested practice, shortcut help,
daily stats, achievements, and every future hover detail. Interactive or
scrollable popovers must not use pointer-events: none in a way that makes the
panel close as soon as the pointer enters it. If a popover flips above the
trigger because there is not enough space below, the bridge must flip above the
trigger as well. Acceptance: with a normal mouse path from the trigger center to
the first line, scrollable area, or internal button of the popover, the popover
must remain visible without flicker, closing, or requiring the user to pin it
with a click first.
The duplicate audit appears below the working list in a collapsed details section. It lists every removed duplicate, the kept row, and the original frequency ranks without taking space before the first visible rows. Long secondary explanations, including the suggested-practice ranking guide and the Chrome extension install guide, sit in the same collapsed stack immediately below the duplicate audit. Keeping these collapsible sections together preserves an orderly, tidy, and visually clean page instead of scattering long help blocks around stats and settings.
The page supports 10, 20, 50, 100, and custom page sizes. It defaults to 20 items per page. Pagination controls appear both above and below the problem table, with first page, previous page, next page, last page, and a page number jump input. Left and right arrow keys turn pages when the current focus is not inside search, filters, selectors, the practice editor, or another editable control.
The top of the page is intentionally compact. A single-line title/action row stays at the page opening for orientation, while summary and stats move below the working list. Search, filters, pagination, and the problem rows remain the first visual priority and should appear without excessive scrolling.
Filters are grouped by scope, ByteDance, and practice state. Scope includes all problems, Hot 100, and sourced company follow-ups. ByteDance includes all, past 30 days, past 3 months, past 6 months, and more than 6 months ago. State includes unsolved, needs thought, and not mastered. Text search is centered on the problem itself: id, Chinese title, and English slug are weighted highest; series names, LingShen topic names, and tags are secondary; Hot 100, ByteDance, and LingShen collection markers are only low-weight helpers. Search results are ordered by relevance first, then by the active filter’s normal order as a tie-breaker. Study-check answers, company follow-ups, implementation sources, and related-problem text no longer pull unrelated high-frequency rows ahead of title matches. Matching supports basic fuzziness: case and full-width normalization, space/hyphen equivalence, all-token matches, prefix/substring matches, and short ordered-character matches.
Clicking a row opens a local practice panel. The panel stores drafts only in
the current browser’s local storage and provides language selection, official
code-template initialization, editing, copy, reset, direct LeetCode link, and
optional extension submit. Code drafts roll on Beijing calendar days: the first
page load in a browser only stamps the current day, and later day changes clear
all code drafts so each day starts from official templates or local fallbacks
again. This rollover affects only code drafts; it does not clear solved status,
visited links, per-problem PBs, or daily timing history. The footer exposes an
auto-reset switch for this Beijing-midnight rollover; it is on by default and
can be turned off per browser. The language selector comes from the official
codeSnippets synced into the repository. If a problem is still missing an
official template, the page uses a local fallback template and says so. The
practice editor uses a native textarea over a local syntax-highlight layer
covering the common languages in the official templates, avoiding a heavier
editor dependency. The native editor still needs LeetCode-like editing basics:
Enter keeps the current line indentation and adds one indentation level after
opening braces, brackets, parentheses, or Python colons; Tab and Shift+Tab
indent and outdent the current line or selected lines; typing a closing brace,
bracket, or parenthesis on an indentation-only line aligns it back one level.
Plain Backspace in leading indentation deletes back to the previous
4-space tab stop, so an 8-space indent becomes 4 spaces, a 6-space indent
becomes 4 spaces, and a partial indent before the first tab stop clears to the
line start.
The editor shows a fixed line-number gutter synchronized with the textarea and
highlight layer. The editor defaults to an auto-growing height equal to the
current code line count plus one spare line, growing with the code up to a
bounded maximum so short templates do not leave a large blank editor area. A
compact toolbar toggle can switch the editor to a 14-visible-line fixed-height
mode when the user wants a stable panel size;
fixed-height mode remains resizable and scrollable. While the auto-growing
editor is being typed near the bottom of the viewport, the page reveals the
current caret line and keeps it in a comfortable writing zone instead of making
the user manually chase the page. When a default template is first opened,
reset, or selected by language change, focus lands inside the function body
where the user is expected to start writing. The practice-page UI, including
statement text, popovers, timing metrics, keyboard hints, and reward overlays,
defaults to a PingFang-first text stack with Apple and common system sans
fallbacks. This page font is not user-configurable and does not change the code
editor font. Editor appearance controls live in the footer: theme, font, font
size, and line spacing. The default light theme uses the same background as the
page while keeping Cursor Light+ token colors, and the default editor font
mirrors the current Cursor font stack (Monaco, 'Cascadia Code', Consolas, 'Courier New', monospace). The default size and line spacing use a tighter
practice density to reduce vertical space for short templates. Alternate editor
themes, monospace stacks, font sizes, and line spacings remain selectable per
browser.
Reloading the page restores the previous practice view from local storage:
current filters, search text, page size, page number, expanded problem, page
scroll position, editor selection, and editor internal scroll position. If
synced problem data changes and a saved problem is no longer visible under the
saved filters, the page falls back to the matching filtered list without
opening an editor.
Direct practice links override that saved view. A URL with ?problem=<slug> or
?id=<frontendId> clears local search and filters, jumps to the matching
problem’s page, opens its practice panel, and focuses the local editor. The
link never resets or replaces an existing local draft; it only chooses which
problem to open. If the URL target is unknown, the page keeps the saved local
view. Each problem row exposes a compact curved-arrow share action beside the
preview controls. It copies a randomized invitation message plus the
current-language problem=<titleSlug> URL, then shows the full copied text in
a temporary notice anchored near the share action. The notice disappears after
a short delay or on the next page click, so the pasted text can invite another
person to open the same problem directly. The Chinese invitation pool uses
handwritten, playful friend-to-friend copy across several tones such as asking
for help, teasing, pretending to be stuck, inviting a shared solve, and asking
for an AC demo. The picker avoids reusing the most recent tones so repeated
shares feel less repetitive.
When a practice editor is open, the cleaned local problem statement is rendered
as normal page UI directly above the code editor. It is on by default, uses a
moderate reading size rather than code comments, and can be collapsed or shown
again from the statement panel; that visibility choice is saved per browser.
Opening a problem or moving between problems with keyboard navigation frames
the problem title row, statement, and editor together below the sticky header,
so the editor keeps focus without hiding the title or local statement above it.
Editor shortcuts match the primary LeetCode muscle memory: Cmd+'
runs the official example testcases and Cmd+Enter performs a full LeetCode
submit. Inside the editor, Cmd+/ toggles line comments for the current
language while preserving the active selection or caret. Cmd+Left and
Cmd+Shift+Left move or select to the first non-whitespace code character
before falling back to the true line start, matching the LeetCode editor’s
indent-aware line-start behavior. Practice navigation is
also keyboard-first: Option+J or Option+Down opens and focuses the next
visible problem’s editor, while Option+K or Option+Up opens and focuses the
previous one. Default-on local route toggles on the timing board let these
keyboard route jumps ignore database-tagged SQL problems and pure frontend
problems whose templates are only JavaScript/TypeScript, without hiding those
problems from the list. Common page actions must also be keyboard reachable:
/ focuses
search, Option+1 through Option+3 switch scope filters, Option+4 through
Option+8 switch ByteDance filters, Option+9, Option+0, and Option+-
switch state filters, Option+P focuses page jump, and Option+Left /
Option+Right jump to first / last page.
The current problem toolbar supports Cmd+Option+L for language focus,
Cmd+Option+C for copy, Cmd+Option+H for editor height, Cmd+Option+R for
current draft reset, and Cmd+Option+D/S/M for done/review/mastered state.
Timing shortcuts include
Cmd+Option+T for current-problem restart, Cmd+Option+Shift+S for session
restart, and Cmd+Option+Shift+T for clearing the current problem PB and last
Accepted record. Compact shortcut affordances near pagination list every
supported key without adding another tall block at the page end. All hover
popovers must remain open while the pointer moves naturally from the trigger
into the floating content, and close only after the pointer leaves that
content.
Practice timing is automatic. Daily history stays collapsed into a hover/focus
popover so it does not push the first problem rows down. Opening or
keyboard-switching into a problem starts that problem’s forward timer without
requiring a start button. The current-problem timer and session timer count
only foreground practice time: they pause when the document is hidden or the
browser window loses focus, then resume from the accumulated value when the page
is visible and focused again. There is no idle timeout, because reading,
debugging, and thinking without keyboard input are still valid practice time. A
full LeetCode submit that returns Accepted records the elapsed foreground time
from the latest switch/open moment, marks the problem done, updates the
problem’s last Accepted time and personal best, and then resets the
active-attempt timer for any repeat attempt. Running examples does not count as
an Accepted solve. The page also starts a session timer when it loads and shows
current problem time, session elapsed time, distinct session Accepted count,
session average, today versus best daily count, current streak, seven-day
count, and the current problem PB. The Today/Best metric must render as a
compact slash value without spaces, such as 38/42, and must never truncate
with an ellipsis or overlap adjacent metric cards at desktop, tablet, or 320 px
mobile widths. The timing board should reflow to fewer metric columns before
individual metric cards become too narrow for their values. The visible metric
label provides the meaning, while assistive text expands the same value as
today’s solved count and the best daily record. Day boundaries are always
computed in
Asia/Shanghai
(北京时间), not the browser’s current local timezone. Session counters live
only in memory for the current page load; per-problem PB/last Accepted and
daily Accepted summaries persist in the browser practice store. Daily summaries
store the unique solved problems, total Accepted submissions, total Accepted
time, fastest single problem, first Accepted time, and last Accepted time for
each Beijing date. The compact board surfaces comparison cues such as new daily
record, tied daily record, best per-problem solve, fastest daily average,
seven-day activity, and streak status. A collapsed daily-history view shows the last
14 Beijing calendar days for quick comparison. Manual reset controls may
restart the current session timer or restart only the current active problem
timer. A less prominent, confirmed control clears the active problem’s stored
PB and last Accepted record without rolling back daily summaries. The normal
flow remains automatic. Immersive practice flow is a default-off local toggle
available from the timing board button or Cmd+Option+F; when it is enabled,
only a full LeetCode submit that returns Accepted opens the next problem in the
current filter and search order. If route skipping is enabled for SQL or pure
frontend problems, list flow chooses the next problem in that same order that
does not match the enabled skip category. This automatic transition uses the
same problem-title, statement, and editor framing as a manual open, and editor
focus must not immediately scroll that title or statement out of view. Passing
sample runs never trigger this navigation.
Durable practice facts are stored as an append-only IndexedDB event log, not as
whole-object localStorage writes. The event log is scoped to the browser
origin and records full submit attempts, sample-run attempts, Accepted timing,
manual done/review/mastered state changes, and current-problem timing clears.
Opening the page migrates the previous localStorage progress, timing, and
submission-stat JSON into stable legacy snapshot events exactly once, then
rebuilds the visible projection from the event log. localStorage remains only
as a compatibility cache for those projections and as storage for inherently
tab-local or last-write-wins state such as editor drafts, scroll position,
current page view, route toggles, and visited-link styling.
Multiple tabs must therefore append independent facts instead of rewriting the
same JSON blob. After a tab appends an event it broadcasts a lightweight update
with BroadcastChannel and also touches a storage pulse key as a fallback.
Other open tabs reload the event log, rebuild progress, timing, and submission
stats, refresh visible row signals, and refresh the “Suggested practice”
popover. If IndexedDB is unavailable, the page falls back to the older
single-tab localStorage projection behavior, but the normal supported path is
event-log-backed and eventually consistent across tabs.
“Suggested practice” can also hold an immersive flow, but it is not list-order
navigation. The user can start suggested flow from the “Suggested practice”
popover or with Cmd+Option+Shift+F; the page first opens the current top
recommendation and marks the flow state as suggested. After each full submit
that returns Accepted, the page recomputes “Suggested practice” from the latest
local submissions, timing, manual state, and current-session fatigue, then
opens the new highest-ranked recommendation instead of the next visible row.
That automatic recommendation jump follows the same title, statement, and
editor framing rule as list flow.
If route skipping is enabled for SQL or pure frontend problems, matching
problems are removed from this candidate queue before selecting the top
recommendation. The just-Accepted problem is not immediately recommended back
to itself. If no recommendable problem exists, the page stays on the current
problem and shows a status cue. Non-Accepted submits and passed sample runs
never advance suggested flow.
The page also tracks a same-day one-shot Accepted combo. This combo is scoped to the Beijing calendar day and resets to zero at 00:00 Asia/Shanghai; the best historical combo is stored and shown separately. The unit is not a problem, but a fresh attempt that starts from the official default template or local fallback template. A fresh attempt starts when a problem is opened without a draft, when the current draft is reset, when the language switch recreates the default template, or when the Beijing-day draft rollover clears code back to defaults. An older problem that was already Accepted can therefore count again after its editor has returned to the default template and the user rewrites it.
A fresh attempt increases the same-day one-shot combo only when the user has made a meaningful code change from the template, no official-example run in that attempt has failed, no full submit in that attempt has failed, and the first full submit for that attempt returns Accepted. Running examples is optional; a direct full submit can count as long as no sample run failed before it. A failed sample run or failed full submit during a fresh attempt immediately breaks the current same-day combo and disqualifies that attempt from later combo credit, even if the user fixes the code and later gets Accepted. Extension installation errors, login errors, network failures, request timeouts, or other cases that do not return a final LeetCode judge result do not change the combo. After an attempt has already been counted, repeated Accepted submits, no-op submits, small edits, or later failures on the same unrestarted code are neutral: they neither increase nor break the combo. A new combo-eligible round requires returning to the default template first.
The one-shot combo UI belongs on the timing board beside the existing practice metrics and inside the active editor’s compact meter. The active editor signal must distinguish a one-shot candidate, a sample-failed round, a submit-failed round, a counted round, and a neutral repeat submit. Accepted combo increments trigger non-blocking reward feedback: the page may draw fireworks, light trails, record pulses, and randomized encouragement copy in a fixed overlay, but it must never steal focus, require confirmation, block typing, or move layout. The encouragement headline and subtitle must use the same default PingFang-first text stack as the rest of the practice UI, even when the fixed overlay is created dynamically. Reward intensity should scale from ordinary combo increments, to milestone counts, to very prominent new-record celebrations. Reduced-motion users should receive a quieter static cue instead of heavy particle animation.
The badge wall has 99 badges and counts only full LeetCode submissions initiated
from this page, and only after LeetCode returns Accepted. Manual Done, Review,
and Mastered state, passed sample runs, opened problem links, and historical
LeetCode submissions do not count. Badge unlocks are also written to the same
IndexedDB event log as achievement-unlocked events. The page derives badge
progress from real submit, timing, topic-tag, and one-shot projections, then
appends an unlock event for any completed badge that has not been recorded yet.
The badge entry sits after the search field as a compact button; hover, focus,
or click opens a game-style badge wall. Ordinary locked badges show their title,
progress, and condition. Hidden locked badges render as ??? with only a vague
hint, and show their real title and description only after unlock. Unlock
feedback must be limited to a non-blocking toast or button pulse; it must not
steal editor focus or change the problem-list layout. Endgame badges should
cover extremely difficult goals such as every problem Accepted, every difficulty
completed, a full-year Accepted streak, a hundred-problem day, and complete
topic tracks.
Full submissions and official-example runs made through this page also append to a separate local submission-stat store. The store does not import historical LeetCode records; it only records actions initiated from the local editor after this feature exists. For each problem it tracks submit attempts, Accepted count, failed submit count, failed sample-run count, latest code size, Accepted time, average Accepted time, and time per 10 nonblank code lines. A compact “Suggested practice” button opens a hover/focus popover, and its ranking is modeled as browser-local practice scheduling instead of a single weakness score.
The final “Suggested practice” score is still clamped to 0 to 100, but it is composed from five explainable parts: review due-ness, weakness, problem value, current fit, and fatigue penalty. Review due-ness estimates a local stability and retrievability for each problem. Full Accepted submissions, recent Accepted streaks, passed sample runs, and manual mastered state increase stability; failures, slow normalized Accepted time, and manual review state lower it. As days since last Accepted increase, retrievability falls and due-ness rises; problems without a full Accepted are treated as not having established stable memory yet. Weakness still uses missing full Accepted evidence, failed submissions, failed sample runs, slow Accepted time normalized by code size, and manual review state. Failed full submissions are stronger than failed sample runs, failure rates are smoothed, and failure counts grow with diminishing returns. Problem value comes from Top 888 frequency, Hot 100 membership, ByteDance company presence, recent ByteDance buckets, tag coverage, LingShen coverage, and related-problem centrality, so a low-value obscure problem does not permanently outrank a slightly weaker high-frequency core problem. Current fit uses the currently open problem, shared tags, related-problem links, and nearby difficulty to prefer same-route transfer or reasonable progression. Fatigue penalty lowers problems already Accepted today, already Accepted in the current session, or heavily overlapping with tags practiced today.
Before score sorting, the scheduler promotes any Hot 100 problem that has no full Accepted evidence above non-Hot 100 candidates. Those promoted Hot 100 problems still use the same scheduling score and tie-breakers to choose their internal order.
The scheduler also supports cold start. A problem can enter the recommendation queue without local submission stats when it is high frequency, in Hot 100, ByteDance-heavy, valuable for tag coverage, or manually marked for review. The popover shows the top ranked problems, final practice score, and the main reason. Problems with local submission evidence still show compact row signals. A collapsed footer note explains the five components, stability, retrievability, cold start, and tie-breakers. The highest score becomes the “Suggested practice” item, and top ranked problems can be opened directly from the popover. The popover also offers a “Start suggested flow” action that holds the recommendation flow. This ranking is intentionally heuristic and browser-local.
Direct LeetCode submission is implemented through the Chrome extension in
extensions/leetcode-submit. The page sends only titleSlug, langSlug, and
the current editor code through window.postMessage for run and submit;
run may also send locally saved extra testcases. The content script forwards
that request to the extension background. The background owns the LeetCode
cookies, queries questionEditorData, runs official examples plus any saved
extra testcases through interpret_solution, posts full submissions to
LeetCode China, and returns the LeetCode submission or interpretation id
quickly. The page then polls the extension with short check requests, and
the extension checks /submissions/detail/{id}/check/ once per request. This
avoids keeping a Manifest V3 message channel open while LeetCode is still
running the job. For compatibility with already-loaded older unpacked
extensions, the page also accepts a finished result returned by the initial
run or submit response before sending check. The page also probes
login-status when a practice editor opens. That response includes an
extension feature version and capability list, so the page can tell whether the
loaded unpacked extension is current and point stale or missing installs to the
installation guide. Cookie values are never sent to page JavaScript or stored
in the repo. If the extension is not installed, outdated, or the user is not
logged in, the page shows that as status and keeps the local editor usable. The
run result panel shows the exact testcase input sent to LeetCode, split into
individual case tabs with parameter names from questionEditorData.metaData.
After the run result arrives, each case shows its submitted code answer,
expected output, and stdout when LeetCode exposes those arrays. The page keeps
compile and runtime diagnostics outside the case tabs because those are not
per-case facts. The run status is considered accepted only when all returned
testcase counts pass. When full submission returns a failed testcase, the page
shows the failing testcase, actual output, expected output, and compile or
runtime diagnostics below the status line, then stores that testcase as an
extra run case for the same problem unless the same normalized testcase is
already saved.
The open editor also lets the user type an extra testcase manually, inspect the
saved extra cases for that problem, remove a single saved case, or clear the
problem’s extra cases. Manual cases use the same normalized local store as
failed-submit cases and are sent only with the next sample run, never with a
full submit.
Extra run cases reset on the next Beijing calendar day, so daily practice
starts from the official examples again.
The page footer also keeps always-visible links to the GitHub repository,
extension directory, latest extension ZIP, feedback issues, and page spec. It
must have comfortable bottom breathing room so the link row never sits flush
against the page end or the viewport edge. The footer also includes a collapsed,
beginner-oriented installation guide for loading or
reloading this unpacked Chrome extension from a GitHub Release package or from
the repository source; the practice editor links directly to this guide and to
the stable latest-release download URL. Extension release tags are named
leetcode-submit-v<manifest version>. Pushing such a tag packages
extensions/leetcode-submit into leetcode-submit.zip and
leetcode-submit-<version>.zip on the GitHub Release. Chrome still installs it
as an unpacked extension, so the guide must say to download the ZIP, unzip it,
load the unzipped folder through chrome://extensions, and reload that
unpacked extension after updating the local folder.
Preview controls include approach, implementation, tags, and related problems.
The statement is not a hover target; it lives above the open editor. Approach,
implementation, and tag previews can be inspected temporarily by hover or
pinned open by click. Hover previews should stay open while the pointer moves
from the trigger into the floating content, then close after the pointer leaves
that content; pinned previews close when the user clicks outside the preview or
presses Escape. The implementation preview is the home for reference
implementation ordering, final reference code, provenance state, and
follow-ups. Reference
implementation code may be committed to this repository and published through
GitHub Pages. The current page starts with harvested recent accepted
submissions for the highest-frequency rows, then fills the rest of the target
set with public, attributed reference implementations. The implementation
preview prefers C++ reference code and applies local C++ syntax highlighting.
When a problem has multiple mainstream approaches, those implementations are
shown in recommended order, following the source solution order where the
source already separates Solution 1, Solution 2, and so on. Problems that are
not C++ problems in LeetCode, such as SQL, JavaScript, Shell, or Pandas
practice rows, show the matching official-language reference instead of
pretending that a C++ submission exists.
Reference implementation coverage is generated and audited locally. The sync
command is npm run sync:leetcode-implementations; it reads public solution
packs and writes src/data/leetcode-implementation-generated.ts. The audit
command is npm run check:leetcode-implementations; it fails if any target row
has no implementation reference, if a row with an official C++ template has no
C++ reference, or if a reference still contains placeholder TODO code. Current
sources are recorded per implementation: recent personal accepted submissions,
Doocs LeetCode (CC-BY-SA-4.0), kamyu104 LeetCode-Solutions (MIT), and a
small set of generated-original fallbacks for sparse LCP/LCCI gaps. Every
external reference keeps its source URL, source title, license label, language,
and provenance label in the hover card.
Practice State
The site is static, so it cannot store a server-side solve counter. Practice state is stored in the visitor’s browser with local storage:
- Done marks that the problem has been attempted.
- Needs thought marks that it should be revisited.
- Mastered marks that it is currently fluent.
Clicked links use the browser’s visited-link behavior and an additional local visited mark, so links remain visually distinct on later visits in the same browser profile.
Preview Contract
The statement panel uses a short plain-text excerpt from the Chinese problem statement. Prompt-like boilerplate embedded in problem text is removed before rendering.
The approach preview has two layers:
- tag-driven study checks, each with a short answer;
- sourced company follow-ups, each with a short answer, company, and source.
The sourced company list is intentionally conservative. It is not a claim that other companies never asked the same follow-up; it only records what could be verified publicly.