mirror of
https://github.com/prdlk/leetcode.git
synced 2026-11-02 21:22:43 +00:00
Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b5879b6eb | ||
|
|
53136b076c | ||
|
|
95f10980d4 | ||
|
|
c6ecb85507 | ||
|
|
2a69f36e6a | ||
|
|
5e4628b20f | ||
|
|
72a8399e6d | ||
|
|
6ebca68ff8 | ||
|
|
957ddf9849 | ||
|
|
e67cc79f39 | ||
|
|
f086c2b39a |
No files matched your search
@@ -49,8 +49,10 @@ All from the repo root (a Bun workspace over `apps/*`):
|
|||||||
bun run pick # scaffold a solution via leetcode-cli (fuzzy picker; hides problems
|
bun run pick # scaffold a solution via leetcode-cli (fuzzy picker; hides problems
|
||||||
# already under work/, caches index+descriptions in
|
# already under work/, caches index+descriptions in
|
||||||
# ~/.local/share/leetcode/data.db — see apps/cli/db.ts)
|
# ~/.local/share/leetcode/data.db — see apps/cli/db.ts)
|
||||||
bun run test # run ONE solution against LeetCode's judge (not a test suite)
|
bun run test # run ONE solution against LeetCode's judge (not a test suite;
|
||||||
bun run submit # submit ONE solution to LeetCode (same picker as test)
|
# most recently tested first, stamped in the db on exit 0)
|
||||||
|
bun run submit # submit ONE solution to LeetCode (newest scaffold first, nothing
|
||||||
|
# hidden; last_submitted stamped in the db on exit 0)
|
||||||
bun run sync # work/ → apps/docs/content/ pages
|
bun run sync # work/ → apps/docs/content/ pages
|
||||||
bun run dev|build # Blume docs site (runs in apps/docs/)
|
bun run dev|build # Blume docs site (runs in apps/docs/)
|
||||||
bun run close-solved -- --dry-run # issue reconcilers (also DRY_RUN=1)
|
bun run close-solved -- --dry-run # issue reconcilers (also DRY_RUN=1)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
addDays,
|
addDays,
|
||||||
campaignDay,
|
campaignDay,
|
||||||
campaignWeek,
|
campaignWeek,
|
||||||
|
isoWeek,
|
||||||
streak,
|
streak,
|
||||||
} from "./srs.ts";
|
} from "./srs.ts";
|
||||||
|
|
||||||
@@ -61,9 +62,14 @@ export async function buildStats(db: D1Database, today: string): Promise<object>
|
|||||||
const ladder: Record<string, number> = { new: 0, "+2": 0, "+5": 0, "+10": 0, retired: 0 };
|
const ladder: Record<string, number> = { new: 0, "+2": 0, "+5": 0, "+10": 0, retired: 0 };
|
||||||
for (const row of ladderRows) ladder[row.stage] = row.n;
|
for (const row of ladderRows) ladder[row.stage] = row.n;
|
||||||
|
|
||||||
const { results: gates } = await db
|
// gates rows are keyed by ISO week (that's the digest/gate contract), but
|
||||||
|
// the page speaks campaign weeks. The campaign never crosses a year
|
||||||
|
// boundary, so a plain offset converts safely.
|
||||||
|
const isoWeekOffset = isoWeek(CAMPAIGN_START) - 1;
|
||||||
|
const { results: gateRows } = await db
|
||||||
.prepare("SELECT week, issue, pass_rate, closed_on FROM gates ORDER BY week")
|
.prepare("SELECT week, issue, pass_rate, closed_on FROM gates ORDER BY week")
|
||||||
.all<{ week: number; issue: number | null; pass_rate: number | null; closed_on: string | null }>();
|
.all<{ week: number; issue: number | null; pass_rate: number | null; closed_on: string | null }>();
|
||||||
|
const gates = gateRows.map((g) => ({ ...g, week: g.week - isoWeekOffset }));
|
||||||
|
|
||||||
// Review-queue depth for the next 14 days: everything due by that day.
|
// Review-queue depth for the next 14 days: everything due by that day.
|
||||||
const queue: { date: string; due: number }[] = [];
|
const queue: { date: string; due: number }[] = [];
|
||||||
|
|||||||
@@ -10,6 +10,12 @@
|
|||||||
* are ever fetched, and paid-only problems are skipped because GraphQL
|
* are ever fetched, and paid-only problems are skipped because GraphQL
|
||||||
* returns null content for them.
|
* returns null content for them.
|
||||||
*
|
*
|
||||||
|
* A `solutions` table tracks the lifecycle of each work/ file by LC number:
|
||||||
|
* `created_at` (backfilled from the file's birthtime on every picker run),
|
||||||
|
* `last_tested` and `last_submitted` (stamped on exit 0 of leetcode-cli).
|
||||||
|
* The test picker sorts by last_tested, the submit picker by created_at, and
|
||||||
|
* submit hides anything with a last_submitted.
|
||||||
|
*
|
||||||
* Library: side-effect-free on import — nothing is opened or fetched until
|
* Library: side-effect-free on import — nothing is opened or fetched until
|
||||||
* problemDb() is called. Index upserts never touch the description column, so
|
* problemDb() is called. Index upserts never touch the description column, so
|
||||||
* a daily refresh cannot evict cached statements.
|
* a daily refresh cannot evict cached statements.
|
||||||
@@ -27,6 +33,13 @@ export interface Problem {
|
|||||||
paidOnly: boolean;
|
paidOnly: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Lifecycle of one work/ solution, keyed by LC number. ISO timestamps. */
|
||||||
|
export interface SolutionActivity {
|
||||||
|
createdAt: string;
|
||||||
|
lastTested: string | null;
|
||||||
|
lastSubmitted: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
const DIFFICULTY = ["", "Easy", "Medium", "Hard"] as const;
|
const DIFFICULTY = ["", "Easy", "Medium", "Hard"] as const;
|
||||||
const INDEX_TTL_MS = 24 * 60 * 60 * 1000;
|
const INDEX_TTL_MS = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
@@ -109,6 +122,13 @@ export function problemDb(path = DB_PATH) {
|
|||||||
paid_only INTEGER NOT NULL,
|
paid_only INTEGER NOT NULL,
|
||||||
description TEXT
|
description TEXT
|
||||||
);
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS solutions (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
created_at TEXT NOT NULL,
|
||||||
|
last_tested TEXT,
|
||||||
|
last_submitted TEXT
|
||||||
|
);
|
||||||
|
DROP TABLE IF EXISTS submissions;
|
||||||
CREATE TABLE IF NOT EXISTS meta (
|
CREATE TABLE IF NOT EXISTS meta (
|
||||||
key TEXT PRIMARY KEY,
|
key TEXT PRIMARY KEY,
|
||||||
value TEXT NOT NULL
|
value TEXT NOT NULL
|
||||||
@@ -177,6 +197,37 @@ export function problemDb(path = DB_PATH) {
|
|||||||
db.query("UPDATE problems SET description = ?2 WHERE slug = ?1").run(slug, html);
|
db.query("UPDATE problems SET description = ?2 WHERE slug = ?1").run(slug, html);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** Per-solution lifecycle rows keyed by LC number. */
|
||||||
|
solutionActivity(): Map<number, SolutionActivity> {
|
||||||
|
const rows = db
|
||||||
|
.query<{ id: number; created_at: string; last_tested: string | null; last_submitted: string | null }, []>(
|
||||||
|
"SELECT id, created_at, last_tested, last_submitted FROM solutions",
|
||||||
|
)
|
||||||
|
.all();
|
||||||
|
return new Map(
|
||||||
|
rows.map((r) => [r.id, { createdAt: r.created_at, lastTested: r.last_tested, lastSubmitted: r.last_submitted }]),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
/** Register a solution's creation time; existing rows are left alone. */
|
||||||
|
ensureSolution(id: number, createdAt: string): void {
|
||||||
|
db.query("INSERT INTO solutions (id, created_at) VALUES (?1, ?2) ON CONFLICT(id) DO NOTHING").run(id, createdAt);
|
||||||
|
},
|
||||||
|
|
||||||
|
markTested(id: number): void {
|
||||||
|
db.query(
|
||||||
|
`INSERT INTO solutions (id, created_at, last_tested) VALUES (?1, ?2, ?2)
|
||||||
|
ON CONFLICT(id) DO UPDATE SET last_tested = excluded.last_tested`,
|
||||||
|
).run(id, new Date().toISOString());
|
||||||
|
},
|
||||||
|
|
||||||
|
markSubmitted(id: number): void {
|
||||||
|
db.query(
|
||||||
|
`INSERT INTO solutions (id, created_at, last_submitted) VALUES (?1, ?2, ?2)
|
||||||
|
ON CONFLICT(id) DO UPDATE SET last_submitted = excluded.last_submitted`,
|
||||||
|
).run(id, new Date().toISOString());
|
||||||
|
},
|
||||||
|
|
||||||
close(): void {
|
close(): void {
|
||||||
db.close();
|
db.close();
|
||||||
},
|
},
|
||||||
|
|||||||
+59
-6
@@ -1,18 +1,64 @@
|
|||||||
/**
|
/**
|
||||||
* Shared work/ solution picker for the test and submit entries: fuzzy-select
|
* Shared work/ solution picker for the test and submit entries: fuzzy-select
|
||||||
* a solution file, then hand it to leetcode-cli. Library: side-effect-free on
|
* a solution file, then hand it to leetcode-cli.
|
||||||
* import — nothing scans the filesystem until runOnSolution() is called.
|
*
|
||||||
|
* Every run backfills the db's solutions table with created_at (from the
|
||||||
|
* file's birthtime, mtime when the filesystem has none) so ordering works for
|
||||||
|
* files that predate the db. Ordering is per command — test lists the most
|
||||||
|
* recently tested first (never-tested after, by name); submit lists the most
|
||||||
|
* recently created first. Nothing is ever hidden. Exit 0 of leetcode-cli
|
||||||
|
* stamps last_tested / last_submitted.
|
||||||
|
*
|
||||||
|
* Library: side-effect-free on import — nothing scans the filesystem until
|
||||||
|
* runOnSolution() is called.
|
||||||
*/
|
*/
|
||||||
import { autocomplete, cancel, isCancel, log } from "@clack/prompts";
|
import { autocomplete, cancel, isCancel, log } from "@clack/prompts";
|
||||||
import { join, relative } from "node:path";
|
import { statSync } from "node:fs";
|
||||||
|
import { basename, join, relative } from "node:path";
|
||||||
|
import { problemDb } from "./db";
|
||||||
|
|
||||||
const ROOT = join(import.meta.dir, "..", "..");
|
const ROOT = join(import.meta.dir, "..", "..");
|
||||||
const WORK_DIR = join(ROOT, "work");
|
const WORK_DIR = join(ROOT, "work");
|
||||||
|
|
||||||
|
/** Leading LC number of a work/ file, or undefined for unnumbered names. */
|
||||||
|
function lcNumber(rel: string): number | undefined {
|
||||||
|
const m = basename(rel).match(/^(\d+)\./);
|
||||||
|
return m ? Number(m[1]) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/** Fuzzy-pick a solution under work/ and run `leetcode <command>` on it. */
|
/** Fuzzy-pick a solution under work/ and run `leetcode <command>` on it. */
|
||||||
export async function runOnSolution(command: "test" | "submit", message: string): Promise<never> {
|
export async function runOnSolution(command: "test" | "submit", message: string): Promise<never> {
|
||||||
const files = [...new Bun.Glob("**/*.{js,ts,py,java,c,cpp,go,rs,rb,swift,kt,cs}").scanSync({ cwd: WORK_DIR })]
|
const db = problemDb();
|
||||||
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
||||||
|
const scanned = [...new Bun.Glob("**/*.{js,ts,py,java,c,cpp,go,rs,rb,swift,kt,cs}").scanSync({ cwd: WORK_DIR })];
|
||||||
|
|
||||||
|
// register creation times so files older than the db still sort correctly
|
||||||
|
for (const f of scanned) {
|
||||||
|
const num = lcNumber(f);
|
||||||
|
if (num === undefined) continue;
|
||||||
|
const stat = statSync(join(WORK_DIR, f));
|
||||||
|
db.ensureSolution(num, new Date(stat.birthtimeMs || stat.mtimeMs).toISOString());
|
||||||
|
}
|
||||||
|
const activity = db.solutionActivity();
|
||||||
|
|
||||||
|
// test → most recently tested first; submit → most recently created first
|
||||||
|
const sortKey = (f: string) => {
|
||||||
|
const num = lcNumber(f);
|
||||||
|
const row = num === undefined ? undefined : activity.get(num);
|
||||||
|
return (command === "test" ? row?.lastTested : row?.createdAt) ?? undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const files = scanned
|
||||||
|
.sort((a, b) => {
|
||||||
|
const ka = sortKey(a);
|
||||||
|
const kb = sortKey(b);
|
||||||
|
if (ka !== kb) {
|
||||||
|
if (ka === undefined) return 1;
|
||||||
|
if (kb === undefined) return -1;
|
||||||
|
return kb.localeCompare(ka); // ISO timestamps: lexicographic = chronological
|
||||||
|
}
|
||||||
|
return a.localeCompare(b, undefined, { numeric: true });
|
||||||
|
});
|
||||||
|
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
log.error(`No solution files found in ${relative(process.cwd(), WORK_DIR)}/`);
|
log.error(`No solution files found in ${relative(process.cwd(), WORK_DIR)}/`);
|
||||||
@@ -55,5 +101,12 @@ export async function runOnSolution(command: "test" | "submit", message: string)
|
|||||||
],
|
],
|
||||||
{ cwd: ROOT, stdio: ["inherit", "inherit", "inherit"] },
|
{ cwd: ROOT, stdio: ["inherit", "inherit", "inherit"] },
|
||||||
);
|
);
|
||||||
process.exit(await proc.exited);
|
const code = await proc.exited;
|
||||||
|
const num = lcNumber(picked);
|
||||||
|
if (code === 0 && num !== undefined) {
|
||||||
|
if (command === "test") db.markTested(num);
|
||||||
|
else db.markSubmitted(num);
|
||||||
|
}
|
||||||
|
db.close();
|
||||||
|
process.exit(code);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
title: '150. Evaluate Reverse Polish Notation'
|
||||||
|
description: You are given an array of strings tokens that represents an arithmetic expression in a Reverse Polish Notation
|
||||||
|
sidebar:
|
||||||
|
label: 'Evaluate Reverse Polish Notation'
|
||||||
|
badge: 'Medium'
|
||||||
|
---
|
||||||
|
|
||||||
|
<Badge variant="accent">Stack</Badge>
|
||||||
|
|
||||||
|
### Example 1:
|
||||||
|
- Input: `tokens = ["2","1","+","3","*"]`
|
||||||
|
- Output: `9`
|
||||||
|
- Explanation: `((2 + 1`) * `3`) = `9`
|
||||||
|
|
||||||
|
### Example 2:
|
||||||
|
- Input: `tokens = ["4","13","5","/","+"]`
|
||||||
|
- Output: `6`
|
||||||
|
- Explanation: `(4 + (13 / 5`)) = `6`
|
||||||
|
|
||||||
|
### Example 3:
|
||||||
|
- Input: `tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]`
|
||||||
|
- Output: `22`
|
||||||
|
- Explanation: `((10 * (6 / ((9 + 3`) * `-11`))) + `17`) + `5 = ((10 * (6 / (12 * -11`))) + `17`) + `5 = ((10 * (6 / -132`)) + `17`) + `5 = ((10 * 0`) + `17`) + `5 = (0 + 17`) + `5 = 17 + 5 = 22`
|
||||||
|
|
||||||
|
### Constraints:
|
||||||
|
|
||||||
|
- `1 <= tokens.length <= 10^4`
|
||||||
|
- `tokens[i]` is either an operator: "+", "-", "*", or "/", or an integer in the range [-200, 200].
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Solution:
|
||||||
|
def evalRPN(self, tokens: List[str]) -> int:
|
||||||
|
stack = []
|
||||||
|
operations = {
|
||||||
|
"+": lambda x, y: int(x + y),
|
||||||
|
"-": lambda x, y: int(x - y),
|
||||||
|
"*": lambda x, y: int(x * y),
|
||||||
|
"/": lambda x, y: int(x / y),
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in tokens:
|
||||||
|
if c in operations:
|
||||||
|
y = stack.pop()
|
||||||
|
x = stack.pop()
|
||||||
|
calc_func = operations[c]
|
||||||
|
result = calc_func(x, y)
|
||||||
|
stack.append(result)
|
||||||
|
else:
|
||||||
|
stack.append(int(c))
|
||||||
|
|
||||||
|
return stack[0]
|
||||||
|
```
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
title: '153. Find Minimum in Rotated Sorted Array'
|
||||||
|
description: 'Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:'
|
||||||
|
sidebar:
|
||||||
|
label: 'Find Minimum in Rotated Sorted Array'
|
||||||
|
badge: 'Medium'
|
||||||
|
---
|
||||||
|
|
||||||
|
<Badge variant="accent">Binary Search</Badge>
|
||||||
|
|
||||||
|
::::warning
|
||||||
|
Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]].
|
||||||
|
::::
|
||||||
|
|
||||||
|
### Example 1:
|
||||||
|
- Input: `nums = [3,4,5,1,2]`
|
||||||
|
- Output: `1`
|
||||||
|
- Explanation: The original array was `[1,2,3,4,5]` rotated `3` times.
|
||||||
|
|
||||||
|
### Example 2:
|
||||||
|
- Input: `nums = [4,5,6,7,0,1,2]`
|
||||||
|
- Output: `0`
|
||||||
|
- Explanation: The original array was `[0,1,2,4,5,6,7]` and it was rotated `4` times.
|
||||||
|
|
||||||
|
### Example 3:
|
||||||
|
- Input: `nums = [11,13,15,17]`
|
||||||
|
- Output: `11`
|
||||||
|
- Explanation: The original array was `[11,13,15,17]` and it was rotated `4` times.
|
||||||
|
|
||||||
|
### Constraints:
|
||||||
|
|
||||||
|
- `n == nums.length`
|
||||||
|
- `1 <= n <= 5000`
|
||||||
|
- `-5000 <= nums[i] <= 5000`
|
||||||
|
- All the integers of `nums` are unique.
|
||||||
|
- `nums` is sorted and rotated between 1 and `n` times.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Solution:
|
||||||
|
def findMin(self, nums: List[int]) -> int:
|
||||||
|
l, r = 0, len(nums) - 1
|
||||||
|
lowest_index = -1
|
||||||
|
|
||||||
|
while l <= r:
|
||||||
|
m = (l + r) // 2
|
||||||
|
if nums[m] <= nums[-1]:
|
||||||
|
lowest_index = m
|
||||||
|
r = m - 1
|
||||||
|
else:
|
||||||
|
l = m + 1
|
||||||
|
|
||||||
|
return nums[lowest_index]
|
||||||
|
```
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
---
|
|
||||||
title: '189. Rotate Array'
|
|
||||||
description: Given an integer array nums, rotate the array to the right by k steps, where k is non-negative
|
|
||||||
sidebar:
|
|
||||||
label: 'Rotate Array'
|
|
||||||
badge: 'Medium'
|
|
||||||
---
|
|
||||||
|
|
||||||
<Badge variant="accent">Two Pointers</Badge>
|
|
||||||
|
|
||||||
::::warning
|
|
||||||
Try to come up with as many solutions as you can. There are at least three different ways to solve this problem. Could you do it in-place with `O(1)` extra space?
|
|
||||||
::::
|
|
||||||
|
|
||||||
### Example 1:
|
|
||||||
- Input: `nums = [1,2,3,4,5,6,7], k = 3`
|
|
||||||
- Output: `[5,6,7,1,2,3,4]`
|
|
||||||
- Explanation: rotate 1 steps to the right: `[7,1,2,3,4,5,6]` rotate 2 steps to the right: `[6,7,1,2,3,4,5]` rotate 3 steps to the right: `[5,6,7,1,2,3,4]`
|
|
||||||
|
|
||||||
### Example 2:
|
|
||||||
- Input: `nums = [-1,-100,3,99], k = 2`
|
|
||||||
- Output: `[3,99,-1,-100]`
|
|
||||||
- Explanation: rotate 1 steps to the right: `[99,-1,-100,3]` rotate 2 steps to the right: `[3,99,-1,-100]`
|
|
||||||
|
|
||||||
### Constraints:
|
|
||||||
|
|
||||||
- `1 <= nums.length <= 10^5`
|
|
||||||
- `-2^31 <= nums[i] <= 2^31 - 1`
|
|
||||||
- `0 <= k <= 10^5`
|
|
||||||
|
|
||||||
## Solution
|
|
||||||
|
|
||||||
```js
|
|
||||||
/**
|
|
||||||
* @param {number[]} nums
|
|
||||||
* @param {number} k
|
|
||||||
* @return {void} Do not return anything, modify nums in-place instead.
|
|
||||||
*/
|
|
||||||
var rotate = function(nums, k) {
|
|
||||||
|
|
||||||
};
|
|
||||||
```
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
---
|
|
||||||
title: '2090. K Radius Subarray Averages'
|
|
||||||
description: You are given a 0-indexed array nums of n integers, and an integer k
|
|
||||||
sidebar:
|
|
||||||
label: 'K Radius Subarray Averages'
|
|
||||||
badge: 'Medium'
|
|
||||||
---
|
|
||||||
|
|
||||||
<Badge variant="accent">Array</Badge>
|
|
||||||
|
|
||||||
### Example 1:
|
|
||||||
- Input: `nums = [7,4,3,9,1,8,5,2,6], k = 3`
|
|
||||||
- Output: `[-1,-1,-1,5,4,4,-1,-1,-1]`
|
|
||||||
- Explanation:
|
|
||||||
- `avg[0]`, `avg[1]`, and `avg[2]` are `-1` because there are less than `k` elements before each index.
|
|
||||||
- The sum of the subarray centered at index `3` with radius `3` is: `7 + 4 + 3 + 9 + 1 + 8 + 5 = 37`. Using integer division, `avg[3] = 37 / 7 = 5`.
|
|
||||||
- For the subarray centered at index `4`, `avg[4] = (4 + 3 + 9 + 1 + 8 + 5 + 2) / 7 = 4`.
|
|
||||||
- For the subarray centered at index `5`, `avg[5] = (3 + 9 + 1 + 8 + 5 + 2 + 6) / 7 = 4`.
|
|
||||||
- `avg[6]`, `avg[7]`, and `avg[8]` are `-1` because there are less than `k` elements after each index.
|
|
||||||
|
|
||||||
### Example 2:
|
|
||||||
- Input: `nums = [100000], k = 0`
|
|
||||||
- Output: `[100000]`
|
|
||||||
- Explanation:
|
|
||||||
- The sum of the subarray centered at index `0` with radius `0` is: `100000`. `avg[0] = 100000 / 1 = 100000`.
|
|
||||||
|
|
||||||
### Example 3:
|
|
||||||
- Input: `nums = [8], k = 100000`
|
|
||||||
- Output: `[-1]`
|
|
||||||
- Explanation:
|
|
||||||
- `avg[0]` is `-1` because there are less than `k` elements before and after index `0`.
|
|
||||||
|
|
||||||
### Constraints:
|
|
||||||
|
|
||||||
- `n == nums.length`
|
|
||||||
- `1 <= n <= 10^5`
|
|
||||||
- `0 <= nums[i], k <= 10^5`
|
|
||||||
|
|
||||||
## Solution
|
|
||||||
|
|
||||||
```js
|
|
||||||
/**
|
|
||||||
* @param {number[]} nums
|
|
||||||
* @param {number} k
|
|
||||||
* @return {number[]}
|
|
||||||
*/
|
|
||||||
var getAverages = function(nums, k) {
|
|
||||||
|
|
||||||
};
|
|
||||||
```
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
title: '35. Search Insert Position'
|
||||||
|
description: Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order
|
||||||
|
sidebar:
|
||||||
|
label: 'Search Insert Position'
|
||||||
|
badge: 'Easy'
|
||||||
|
---
|
||||||
|
|
||||||
|
<Badge variant="accent">Binary Search</Badge>
|
||||||
|
|
||||||
|
::::warning
|
||||||
|
You must write an algorithm with O(log n) runtime complexity.
|
||||||
|
::::
|
||||||
|
|
||||||
|
### Example 1:
|
||||||
|
- Input: `nums = [1,3,5,6], target = 5`
|
||||||
|
- Output: `2`
|
||||||
|
|
||||||
|
### Example 2:
|
||||||
|
- Input: `nums = [1,3,5,6], target = 2`
|
||||||
|
- Output: `1`
|
||||||
|
|
||||||
|
### Example 3:
|
||||||
|
- Input: `nums = [1,3,5,6], target = 7`
|
||||||
|
- Output: `4`
|
||||||
|
|
||||||
|
### Constraints:
|
||||||
|
|
||||||
|
- `1 <= nums.length <= 10^4`
|
||||||
|
- `-10^4 <= nums[i] <= 10^4`
|
||||||
|
- `nums` contains distinct values sorted in ascending order.
|
||||||
|
- `-10^4 <= target <= 10^4`
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Solution:
|
||||||
|
def searchInsert(self, nums: List[int], target: int) -> int:
|
||||||
|
l, r = 0, len(nums) - 1
|
||||||
|
|
||||||
|
while l <= r:
|
||||||
|
m = (l + r) // 2
|
||||||
|
if nums[m] == target:
|
||||||
|
return m
|
||||||
|
elif nums[m] < target:
|
||||||
|
l = m + 1
|
||||||
|
elif nums[m] > target:
|
||||||
|
r = m - 1
|
||||||
|
|
||||||
|
return (l + r) // 2 + 1
|
||||||
|
```
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
---
|
|
||||||
title: '42. Trapping Rain Water'
|
|
||||||
description: Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining
|
|
||||||
sidebar:
|
|
||||||
label: 'Trapping Rain Water'
|
|
||||||
badge: 'Hard'
|
|
||||||
---
|
|
||||||
|
|
||||||
<Badge variant="accent">Two Pointers</Badge>
|
|
||||||
|
|
||||||
### Example 1:
|
|
||||||
- Input: `height = [0,1,0,2,1,0,1,3,2,1,2,1]`
|
|
||||||
- Output: `6`
|
|
||||||
- Explanation: The above elevation map (black section) is represented by array `[0,1,0,2,1,0,1,3,2,1,2,1]`. In this case, `6` units of rain water (blue section) are being trapped.
|
|
||||||
|
|
||||||
### Example 2:
|
|
||||||
- Input: `height = [4,2,0,3,2,5]`
|
|
||||||
- Output: `9`
|
|
||||||
|
|
||||||
### Constraints:
|
|
||||||
|
|
||||||
- `n == height.length`
|
|
||||||
- `1 <= n <= 2 * 10^4`
|
|
||||||
- `0 <= height[i] <= 10^5`
|
|
||||||
|
|
||||||
## Solution
|
|
||||||
|
|
||||||
```js
|
|
||||||
/**
|
|
||||||
* @param {number[]} height
|
|
||||||
* @return {number}
|
|
||||||
*/
|
|
||||||
var trap = function(height) {
|
|
||||||
|
|
||||||
};
|
|
||||||
```
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
title: '155. Min Stack'
|
||||||
|
description: Design a stack that supports push, pop, top, and retrieving the minimum element in constant time
|
||||||
|
sidebar:
|
||||||
|
label: 'Min Stack'
|
||||||
|
badge: 'Medium'
|
||||||
|
---
|
||||||
|
|
||||||
|
<Badge variant="accent">Stack</Badge>
|
||||||
|
|
||||||
|
::::warning
|
||||||
|
You must implement a solution with O(1) time complexity for each function.
|
||||||
|
::::
|
||||||
|
|
||||||
|
### Example 1:
|
||||||
|
- Input: ``
|
||||||
|
- Output: ``
|
||||||
|
- Explanation: Input `["MinStack","push","push","push","getMin","pop","top","getMin"]` [[],[-2],[0],[-3],[],[],[],[]] Output `[null,null,null,null,-3,null,0,-2]` Explanation MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); // return `-3` minStack.pop(); minStack.top(); // return `0` minStack.getMin(); // return `-2`
|
||||||
|
|
||||||
|
### Constraints:
|
||||||
|
|
||||||
|
- `-2^31 <= val <= 2^31 - 1`
|
||||||
|
- Methods pop, top and getMin operations will always be called on non-empty stacks.
|
||||||
|
- At most 3 * 10^4 calls will be made to push, pop, top, and getMin.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
```py
|
||||||
|
class MinStack:
|
||||||
|
def __init__(self):
|
||||||
|
self.stack = []
|
||||||
|
self.minStack = []
|
||||||
|
|
||||||
|
def push(self, value: int) -> None:
|
||||||
|
self.stack.append(value)
|
||||||
|
value = min(value, self.minStack[-1] if self.minStack else value)
|
||||||
|
self.minStack.append(value)
|
||||||
|
|
||||||
|
def pop(self) -> None:
|
||||||
|
self.stack.pop()
|
||||||
|
self.minStack.pop()
|
||||||
|
|
||||||
|
def top(self) -> int:
|
||||||
|
return self.stack[-1]
|
||||||
|
|
||||||
|
def getMin(self) -> int:
|
||||||
|
return self.minStack[-1]
|
||||||
|
|
||||||
|
|
||||||
|
# Your MinStack object will be instantiated and called as such:
|
||||||
|
# obj = MinStack()
|
||||||
|
# obj.push(value)
|
||||||
|
# obj.pop()
|
||||||
|
# param_3 = obj.top()
|
||||||
|
# param_4 = obj.getMin()
|
||||||
|
```
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
title: '20. Valid Parentheses'
|
||||||
|
description: Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid
|
||||||
|
sidebar:
|
||||||
|
label: 'Valid Parentheses'
|
||||||
|
badge: 'Easy'
|
||||||
|
---
|
||||||
|
|
||||||
|
<Badge variant="accent">Stack</Badge>
|
||||||
|
|
||||||
|
### Example 1:
|
||||||
|
- Input: `s = "()"`
|
||||||
|
- Output: `true`
|
||||||
|
|
||||||
|
### Example 2:
|
||||||
|
- Input: `s = "()[]{}"`
|
||||||
|
- Output: `true`
|
||||||
|
|
||||||
|
### Example 3:
|
||||||
|
- Input: `s = "(]"`
|
||||||
|
- Output: `false`
|
||||||
|
|
||||||
|
### Example 4:
|
||||||
|
- Input: `s = "([])"`
|
||||||
|
- Output: `true`
|
||||||
|
|
||||||
|
### Example 5:
|
||||||
|
- Input: `s = "([)]"`
|
||||||
|
- Output: `false`
|
||||||
|
|
||||||
|
### Constraints:
|
||||||
|
|
||||||
|
- `1 <= s.length <= 10^4`
|
||||||
|
- `s` consists of parentheses only '()[]{}'.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
```py
|
||||||
|
class Solution:
|
||||||
|
def isValid(self, s: str) -> bool:
|
||||||
|
stack = []
|
||||||
|
pairs = {")": "(", "]": "[", "}": "{"}
|
||||||
|
|
||||||
|
for c in s:
|
||||||
|
if c in pairs:
|
||||||
|
if stack and pairs[c] == stack[-1]:
|
||||||
|
stack.pop()
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
stack.append(c)
|
||||||
|
|
||||||
|
return True if not stack else False
|
||||||
|
```
|
||||||
@@ -35,6 +35,7 @@ interface Stats {
|
|||||||
deferred_total: number;
|
deferred_total: number;
|
||||||
}[];
|
}[];
|
||||||
ladder: Record<Stage, number>;
|
ladder: Record<Stage, number>;
|
||||||
|
/** week is the 1-based campaign week — the Worker converts from ISO. */
|
||||||
gates: {
|
gates: {
|
||||||
week: number;
|
week: number;
|
||||||
issue: number | null;
|
issue: number | null;
|
||||||
@@ -76,7 +77,12 @@ function dayLabel(iso: string): string {
|
|||||||
return `${weekday} ${iso.slice(8)}`;
|
return `${weekday} ${iso.slice(8)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── shared styles (theme tokens only — no hand-rolled palette) ───
|
// ── shared styles ────────────────────────────────────────────────
|
||||||
|
// Theme tokens only, with two deliberate exceptions: the phase-bar sets get
|
||||||
|
// fixed hues (accent-blue core, yellow optional, red deferred — they must be
|
||||||
|
// distinguishable, not shades of one colour), and the last-7-days heatmap
|
||||||
|
// reuses the GREENS ramp from apps/api/src/charts.ts so the page matches the
|
||||||
|
// README/email heatmaps (level 0 stays a theme token so light mode works).
|
||||||
|
|
||||||
const card: CSSProperties = {
|
const card: CSSProperties = {
|
||||||
border: "1px solid var(--blume-border)",
|
border: "1px solid var(--blume-border)",
|
||||||
@@ -142,32 +148,78 @@ function Header({ stats }: { stats: Stats }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// One stacked bar per phase: solved core / optional / deferred segments over
|
||||||
|
// a muted track sized by the phase's total problem count, so both phase size
|
||||||
|
// and progress read at a glance.
|
||||||
|
const SETS = [
|
||||||
|
["core", "var(--blume-accent)"],
|
||||||
|
["optional", "#d29922"],
|
||||||
|
["deferred", "#e5534b"],
|
||||||
|
] as const;
|
||||||
|
|
||||||
function Phases({ stats }: { stats: Stats }) {
|
function Phases({ stats }: { stats: Stats }) {
|
||||||
|
const maxTotal = Math.max(
|
||||||
|
1,
|
||||||
|
...stats.phases.map((p) => p.core_total + p.optional_total + p.deferred_total),
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div style={card}>
|
<div style={card}>
|
||||||
<div style={heading}>Phases</div>
|
<div style={heading}>Phases</div>
|
||||||
<table style={{ borderCollapse: "collapse", width: "100%" }}>
|
<div style={{ display: "flex", gap: "1rem", flexWrap: "wrap", marginBottom: "0.6rem" }}>
|
||||||
<tbody>
|
{SETS.map(([set, color]) => (
|
||||||
{stats.phases.map((p) => (
|
<span key={set} style={muted}>
|
||||||
<tr key={p.milestone}>
|
<span
|
||||||
<td style={{ padding: "0.2rem 1rem 0.2rem 0" }}>{p.name}</td>
|
style={{
|
||||||
<td style={{ padding: "0.2rem 1rem 0.2rem 0" }}>
|
display: "inline-block",
|
||||||
<Bar done={p.core_done} total={p.core_total} />{" "}
|
width: "0.65rem",
|
||||||
<span style={muted}>
|
height: "0.65rem",
|
||||||
core {p.core_done}/{p.core_total}
|
borderRadius: "2px",
|
||||||
</span>
|
background: color,
|
||||||
</td>
|
marginRight: "0.35rem",
|
||||||
<td style={{ padding: "0.2rem 0" }}>
|
}}
|
||||||
<span style={muted}>
|
/>
|
||||||
optional {p.optional_done}/{p.optional_total}
|
{set}
|
||||||
{p.deferred_total > 0 &&
|
</span>
|
||||||
` · deferred ${p.deferred_done}/${p.deferred_total}`}
|
))}
|
||||||
</span>
|
</div>
|
||||||
</td>
|
{stats.phases.map((p) => {
|
||||||
</tr>
|
const total = p.core_total + p.optional_total + p.deferred_total;
|
||||||
))}
|
const done = p.core_done + p.optional_done + p.deferred_done;
|
||||||
</tbody>
|
return (
|
||||||
</table>
|
<div
|
||||||
|
key={p.milestone}
|
||||||
|
title={`core ${p.core_done}/${p.core_total} · optional ${p.optional_done}/${p.optional_total} · deferred ${p.deferred_done}/${p.deferred_total}`}
|
||||||
|
style={{ display: "flex", alignItems: "center", gap: "0.75rem", padding: "0.25rem 0" }}
|
||||||
|
>
|
||||||
|
<span style={{ width: "9.5rem", flexShrink: 0 }}>{p.name}</span>
|
||||||
|
<span style={{ flex: 1 }}>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
width: `${(total / maxTotal) * 100}%`,
|
||||||
|
height: "0.65rem",
|
||||||
|
borderRadius: "var(--blume-radius)",
|
||||||
|
background: "var(--blume-muted)",
|
||||||
|
overflow: "hidden",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{SETS.map(([set, color]) => {
|
||||||
|
const solved = p[`${set}_done`];
|
||||||
|
return solved > 0 ? (
|
||||||
|
<span
|
||||||
|
key={set}
|
||||||
|
style={{ width: `${(solved / total) * 100}%`, background: color }}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span style={{ ...muted, width: "3.5rem", textAlign: "right", flexShrink: 0 }}>
|
||||||
|
{done}/{total}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -224,76 +276,95 @@ function Gates({ stats }: { stats: Stats }) {
|
|||||||
<div style={card}>
|
<div style={card}>
|
||||||
<div style={heading}>Gate log</div>
|
<div style={heading}>Gate log</div>
|
||||||
{stats.gates.length === 0 ? (
|
{stats.gates.length === 0 ? (
|
||||||
<span style={muted}>No gates yet.</span>
|
<span style={muted}>No gates yet — the first weekly review opens Saturday night.</span>
|
||||||
) : (
|
) : (
|
||||||
<table style={{ borderCollapse: "collapse", width: "100%" }}>
|
stats.gates.map((g) => (
|
||||||
<thead>
|
<div
|
||||||
<tr>
|
key={g.week}
|
||||||
{["Week", "Issue", "Pass rate", "Closed"].map((h) => (
|
style={{
|
||||||
<th key={h} style={{ ...muted, textAlign: "left", padding: "0.2rem 1rem 0.2rem 0" }}>
|
display: "flex",
|
||||||
{h}
|
gap: "0.75rem",
|
||||||
</th>
|
alignItems: "baseline",
|
||||||
))}
|
flexWrap: "wrap",
|
||||||
</tr>
|
padding: "0.15rem 0",
|
||||||
</thead>
|
}}
|
||||||
<tbody>
|
>
|
||||||
{stats.gates.map((g) => (
|
<span style={{ width: "4.5rem", flexShrink: 0 }}>Week {g.week}</span>
|
||||||
<tr key={g.week}>
|
{g.issue === null ? (
|
||||||
<td style={{ padding: "0.2rem 1rem 0.2rem 0" }}>{g.week}</td>
|
<span style={muted}>no review issue</span>
|
||||||
<td style={{ padding: "0.2rem 1rem 0.2rem 0" }}>
|
) : (
|
||||||
{g.issue === null ? (
|
<a
|
||||||
<span style={muted}>—</span>
|
href={`https://github.com/prdlk/leetcode/issues/${g.issue}`}
|
||||||
) : (
|
target="_blank"
|
||||||
<a
|
rel="noreferrer"
|
||||||
href={`https://github.com/prdlk/leetcode/issues/${g.issue}`}
|
>
|
||||||
target="_blank"
|
#{g.issue}
|
||||||
rel="noreferrer"
|
</a>
|
||||||
>
|
)}
|
||||||
#{g.issue}
|
{g.pass_rate === null ? (
|
||||||
</a>
|
<span style={muted}>in progress</span>
|
||||||
)}
|
) : (
|
||||||
</td>
|
<span>
|
||||||
<td style={{ padding: "0.2rem 1rem 0.2rem 0" }}>
|
{percent(g.pass_rate)} passed
|
||||||
{g.pass_rate === null ? (
|
{g.closed_on && <span style={muted}> · closed {g.closed_on}</span>}
|
||||||
<span style={muted}>open</span>
|
</span>
|
||||||
) : (
|
)}
|
||||||
percent(g.pass_rate)
|
</div>
|
||||||
)}
|
))
|
||||||
</td>
|
|
||||||
<td style={{ padding: "0.2rem 0" }}>
|
|
||||||
{g.closed_on ?? <span style={muted}>—</span>}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
)}
|
)}
|
||||||
|
<div style={{ ...muted, marginTop: "0.4rem" }}>
|
||||||
|
One gate per campaign week — scored when its review issue closes.
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GREENS ramp from apps/api/src/charts.ts; level 0 swapped for the theme's
|
||||||
|
// muted token so an empty day looks right in both colour schemes.
|
||||||
|
const GREENS = [
|
||||||
|
"var(--blume-muted)",
|
||||||
|
"#0e4429",
|
||||||
|
"#006d32",
|
||||||
|
"#26a641",
|
||||||
|
"#39d353",
|
||||||
|
];
|
||||||
|
|
||||||
function Recent({ stats }: { stats: Stats }) {
|
function Recent({ stats }: { stats: Stats }) {
|
||||||
return (
|
return (
|
||||||
<div style={card}>
|
<div style={card}>
|
||||||
<div style={heading}>Last 7 days</div>
|
<div style={heading}>Last 7 days</div>
|
||||||
<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
|
<div style={{ display: "flex", gap: "0.4rem", flexWrap: "wrap" }}>
|
||||||
{stats.recent.map((r) => (
|
{stats.recent.map((r) => (
|
||||||
<span
|
<span
|
||||||
key={r.date}
|
key={r.date}
|
||||||
style={{
|
title={`${r.date}: ${r.passes}/${r.attempts} passed`}
|
||||||
border: "1px solid var(--blume-border)",
|
style={{ textAlign: "center" }}
|
||||||
borderRadius: "var(--blume-radius)",
|
|
||||||
padding: "0.35rem 0.6rem",
|
|
||||||
textAlign: "center",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<span style={{ ...muted, display: "block" }}>{dayLabel(r.date)}</span>
|
<span
|
||||||
<strong>{r.passes}</strong>
|
style={{
|
||||||
<span style={muted}>/{r.attempts}</span>
|
display: "block",
|
||||||
|
width: "2.6rem",
|
||||||
|
height: "2rem",
|
||||||
|
borderRadius: "var(--blume-radius)",
|
||||||
|
background: GREENS[Math.min(r.attempts, 4)],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span style={{ ...muted, display: "block", marginTop: "0.25rem", fontSize: "0.75em" }}>
|
||||||
|
{dayLabel(r.date)}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ ...muted, marginTop: "0.4rem" }}>passes / attempts</div>
|
<div style={{ ...muted, marginTop: "0.5rem", display: "flex", alignItems: "center", gap: "0.25rem" }}>
|
||||||
|
<span>Less</span>
|
||||||
|
{GREENS.map((color) => (
|
||||||
|
<span
|
||||||
|
key={color}
|
||||||
|
style={{ display: "inline-block", width: "0.65rem", height: "0.65rem", borderRadius: "2px", background: color }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<span>More · colour = attempts, hover for passes</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
"""
|
||||||
|
35. Search Insert Position
|
||||||
|
Difficulty: Easy
|
||||||
|
https://leetcode.com/problems/search-insert-position/
|
||||||
|
|
||||||
|
──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Given a sorted array of distinct integers and a target value, return
|
||||||
|
the index if the target is found. If not, return the index where it
|
||||||
|
would be if it were inserted in order.
|
||||||
|
|
||||||
|
You must write an algorithm with O(log n) runtime complexity.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Example 1:
|
||||||
|
|
||||||
|
Input: nums = [1,3,5,6], target = 5
|
||||||
|
Output: 2
|
||||||
|
|
||||||
|
Example 2:
|
||||||
|
|
||||||
|
Input: nums = [1,3,5,6], target = 2
|
||||||
|
Output: 1
|
||||||
|
|
||||||
|
Example 3:
|
||||||
|
|
||||||
|
Input: nums = [1,3,5,6], target = 7
|
||||||
|
Output: 4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
|
||||||
|
• 1 <= nums.length <= 10^4
|
||||||
|
|
||||||
|
• -10^4 <= nums[i] <= 10^4
|
||||||
|
|
||||||
|
• nums contains distinct values sorted in ascending order.
|
||||||
|
|
||||||
|
• -10^4 <= target <= 10^4
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def searchInsert(self, nums: List[int], target: int) -> int:
|
||||||
|
l, r = 0, len(nums) - 1
|
||||||
|
|
||||||
|
while l <= r:
|
||||||
|
m = (l + r) // 2
|
||||||
|
if nums[m] == target:
|
||||||
|
return m
|
||||||
|
elif nums[m] < target:
|
||||||
|
l = m + 1
|
||||||
|
elif nums[m] > target:
|
||||||
|
r = m - 1
|
||||||
|
|
||||||
|
return (l + r) // 2 + 1
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
"""
|
||||||
|
20. Valid Parentheses
|
||||||
|
Difficulty: Easy
|
||||||
|
https://leetcode.com/problems/valid-parentheses/
|
||||||
|
|
||||||
|
──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Given a string s containing just the characters '(', ')', '{', '}',
|
||||||
|
'[' and ']', determine if the input string is valid.
|
||||||
|
|
||||||
|
An input string is valid if:
|
||||||
|
|
||||||
|
• Open brackets must be closed by the same type of brackets.
|
||||||
|
|
||||||
|
• Open brackets must be closed in the correct order.
|
||||||
|
|
||||||
|
• Every close bracket has a corresponding open bracket of the same
|
||||||
|
type.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Example 1:
|
||||||
|
|
||||||
|
Input: s = "()"
|
||||||
|
|
||||||
|
Output: true
|
||||||
|
|
||||||
|
Example 2:
|
||||||
|
|
||||||
|
Input: s = "()[]{}"
|
||||||
|
|
||||||
|
Output: true
|
||||||
|
|
||||||
|
Example 3:
|
||||||
|
|
||||||
|
Input: s = "(]"
|
||||||
|
|
||||||
|
Output: false
|
||||||
|
|
||||||
|
Example 4:
|
||||||
|
|
||||||
|
Input: s = "([])"
|
||||||
|
|
||||||
|
Output: true
|
||||||
|
|
||||||
|
Example 5:
|
||||||
|
|
||||||
|
Input: s = "([)]"
|
||||||
|
|
||||||
|
Output: false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
|
||||||
|
• 1 <= s.length <= 10^4
|
||||||
|
|
||||||
|
• s consists of parentheses only '()[]{}'.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def isValid(self, s: str) -> bool:
|
||||||
|
stack = []
|
||||||
|
pairs = {")": "(", "]": "[", "}": "{"}
|
||||||
|
|
||||||
|
for c in s:
|
||||||
|
if c in pairs:
|
||||||
|
if stack and pairs[c] == stack[-1]:
|
||||||
|
stack.pop()
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
stack.append(c)
|
||||||
|
|
||||||
|
return True if not stack else False
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* 42. Trapping Rain Water
|
|
||||||
* Difficulty: Hard
|
|
||||||
* https://leetcode.com/problems/trapping-rain-water/
|
|
||||||
*
|
|
||||||
* ──────────────────────────────────────────────────
|
|
||||||
*
|
|
||||||
* Given n non-negative integers representing an elevation map where the
|
|
||||||
* width of each bar is 1, compute how much water it can trap after
|
|
||||||
* raining.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Example 1:
|
|
||||||
*
|
|
||||||
* Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
|
|
||||||
* Output: 6
|
|
||||||
* Explanation: The above elevation map (black section) is represented
|
|
||||||
* by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain
|
|
||||||
* water (blue section) are being trapped.
|
|
||||||
*
|
|
||||||
* Example 2:
|
|
||||||
*
|
|
||||||
* Input: height = [4,2,0,3,2,5]
|
|
||||||
* Output: 9
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Constraints:
|
|
||||||
*
|
|
||||||
* • n == height.length
|
|
||||||
*
|
|
||||||
* • 1 <= n <= 2 * 10^4
|
|
||||||
*
|
|
||||||
* • 0 <= height[i] <= 10^5
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number[]} height
|
|
||||||
* @return {number}
|
|
||||||
*/
|
|
||||||
var trap = function(height) {
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
"""
|
||||||
|
150. Evaluate Reverse Polish Notation
|
||||||
|
Difficulty: Medium
|
||||||
|
https://leetcode.com/problems/evaluate-reverse-polish-notation/
|
||||||
|
|
||||||
|
──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
You are given an array of strings tokens that represents an
|
||||||
|
arithmetic expression in a Reverse Polish Notation.
|
||||||
|
|
||||||
|
Evaluate the expression. Return an integer that represents the value
|
||||||
|
of the expression.
|
||||||
|
|
||||||
|
Note that:
|
||||||
|
|
||||||
|
• The valid operators are '+', '-', '*', and '/'.
|
||||||
|
|
||||||
|
• Each operand may be an integer or another expression.
|
||||||
|
|
||||||
|
• The division between two integers always truncates toward zero.
|
||||||
|
|
||||||
|
• There will not be any division by zero.
|
||||||
|
|
||||||
|
• The input represents a valid arithmetic expression in a reverse
|
||||||
|
polish notation.
|
||||||
|
|
||||||
|
• The answer and all the intermediate calculations can be
|
||||||
|
represented in a 32-bit integer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Example 1:
|
||||||
|
|
||||||
|
Input: tokens = ["2","1","+","3","*"]
|
||||||
|
Output: 9
|
||||||
|
Explanation: ((2 + 1) * 3) = 9
|
||||||
|
|
||||||
|
Example 2:
|
||||||
|
|
||||||
|
Input: tokens = ["4","13","5","/","+"]
|
||||||
|
Output: 6
|
||||||
|
Explanation: (4 + (13 / 5)) = 6
|
||||||
|
|
||||||
|
Example 3:
|
||||||
|
|
||||||
|
Input: tokens =
|
||||||
|
["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
|
||||||
|
Output: 22
|
||||||
|
Explanation: ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
|
||||||
|
= ((10 * (6 / (12 * -11))) + 17) + 5
|
||||||
|
= ((10 * (6 / -132)) + 17) + 5
|
||||||
|
= ((10 * 0) + 17) + 5
|
||||||
|
= (0 + 17) + 5
|
||||||
|
= 17 + 5
|
||||||
|
= 22
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
|
||||||
|
• 1 <= tokens.length <= 10^4
|
||||||
|
|
||||||
|
• tokens[i] is either an operator: "+", "-", "*", or "/", or an
|
||||||
|
integer in the range [-200, 200].
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def evalRPN(self, tokens: List[str]) -> int:
|
||||||
|
stack = []
|
||||||
|
operations = {
|
||||||
|
"+": lambda x, y: int(x + y),
|
||||||
|
"-": lambda x, y: int(x - y),
|
||||||
|
"*": lambda x, y: int(x * y),
|
||||||
|
"/": lambda x, y: int(x / y),
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in tokens:
|
||||||
|
if c in operations:
|
||||||
|
y = stack.pop()
|
||||||
|
x = stack.pop()
|
||||||
|
calc_func = operations[c]
|
||||||
|
result = calc_func(x, y)
|
||||||
|
stack.append(result)
|
||||||
|
else:
|
||||||
|
stack.append(int(c))
|
||||||
|
|
||||||
|
return stack[0]
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
"""
|
||||||
|
155. Min Stack
|
||||||
|
Difficulty: Medium
|
||||||
|
https://leetcode.com/problems/min-stack/
|
||||||
|
|
||||||
|
──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Design a stack that supports push, pop, top, and retrieving the
|
||||||
|
minimum element in constant time.
|
||||||
|
|
||||||
|
Implement the MinStack class:
|
||||||
|
|
||||||
|
• MinStack() initializes the stack object.
|
||||||
|
|
||||||
|
• void push(int value) pushes the element value onto the stack.
|
||||||
|
|
||||||
|
• void pop() removes the element on the top of the stack.
|
||||||
|
|
||||||
|
• int top() gets the top element of the stack.
|
||||||
|
|
||||||
|
• int getMin() retrieves the minimum element in the stack.
|
||||||
|
|
||||||
|
You must implement a solution with O(1) time complexity for each
|
||||||
|
function.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Example 1:
|
||||||
|
|
||||||
|
Input
|
||||||
|
["MinStack","push","push","push","getMin","pop","top","getMin"]
|
||||||
|
[[],[-2],[0],[-3],[],[],[],[]]
|
||||||
|
|
||||||
|
Output
|
||||||
|
[null,null,null,null,-3,null,0,-2]
|
||||||
|
|
||||||
|
Explanation
|
||||||
|
MinStack minStack = new MinStack();
|
||||||
|
minStack.push(-2);
|
||||||
|
minStack.push(0);
|
||||||
|
minStack.push(-3);
|
||||||
|
minStack.getMin(); // return -3
|
||||||
|
minStack.pop();
|
||||||
|
minStack.top(); // return 0
|
||||||
|
minStack.getMin(); // return -2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
|
||||||
|
• -2^31 <= val <= 2^31 - 1
|
||||||
|
|
||||||
|
• Methods pop, top and getMin operations will always be called on
|
||||||
|
non-empty stacks.
|
||||||
|
|
||||||
|
• At most 3 * 10^4 calls will be made to push, pop, top, and getMin.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class MinStack:
|
||||||
|
def __init__(self):
|
||||||
|
self.stack = []
|
||||||
|
self.minStack = []
|
||||||
|
|
||||||
|
def push(self, value: int) -> None:
|
||||||
|
self.stack.append(value)
|
||||||
|
value = min(value, self.minStack[-1] if self.minStack else value)
|
||||||
|
self.minStack.append(value)
|
||||||
|
|
||||||
|
def pop(self) -> None:
|
||||||
|
self.stack.pop()
|
||||||
|
self.minStack.pop()
|
||||||
|
|
||||||
|
def top(self) -> int:
|
||||||
|
return self.stack[-1]
|
||||||
|
|
||||||
|
def getMin(self) -> int:
|
||||||
|
return self.minStack[-1]
|
||||||
|
|
||||||
|
|
||||||
|
# Your MinStack object will be instantiated and called as such:
|
||||||
|
# obj = MinStack()
|
||||||
|
# obj.push(value)
|
||||||
|
# obj.pop()
|
||||||
|
# param_3 = obj.top()
|
||||||
|
# param_4 = obj.getMin()
|
||||||
Reference in new issue
Block a user