From 14d05011d559d8d60b87d06658e16e8a38d2115c Mon Sep 17 00:00:00 2001 From: Wong Ding Feng Date: Fri, 5 Jun 2026 22:18:39 +0800 Subject: [PATCH] upd --- org/study_deck_02/.dir-locals.el | 5 +- org/study_deck_02/AGENTS.md | 12 +- .../dsa/arrays-hashing/0001-two-sum.org | 6 + .../0347-top-k-frequent-elements.org | 4 +- .../1408-string-matching-in-an-array.org | 30 +++++ org/study_deck_02/roadmap.org | 6 +- org/study_deck_02/toolkit/notes.org | 113 ++++++++++++++++++ 7 files changed, 169 insertions(+), 7 deletions(-) diff --git a/org/study_deck_02/.dir-locals.el b/org/study_deck_02/.dir-locals.el index 8c70cfa..94f0656 100644 --- a/org/study_deck_02/.dir-locals.el +++ b/org/study_deck_02/.dir-locals.el @@ -1 +1,4 @@ -((org-mode . ((org-todo-keywords . ((sequence "TODO" | "DONE" "TOO_EASY")))))) +((org-mode . ((org-todo-keywords . ((sequence "TODO" | "DONE" "TOO_EASY"))) + (eval . (let ((lc-el (expand-file-name "lc-org.el" (dir-locals-find-file default-directory)))) + (when (and lc-el (file-exists-p lc-el) (not (featurep 'lc-org))) + (load-file lc-el))))))) diff --git a/org/study_deck_02/AGENTS.md b/org/study_deck_02/AGENTS.md index bdde0b0..148b1cb 100644 --- a/org/study_deck_02/AGENTS.md +++ b/org/study_deck_02/AGENTS.md @@ -14,7 +14,12 @@ An Anki-exportable study deck for NeetCode DSA problems. - Python and C++ solution stubs - A `NEETCODE` property linking back to the roadmap -3. **Study flow** — open roadmap.org, pick a topic, pick a problem, +3. **Toolkit** (`toolkit/`) — your reference library: + - `tricks.org` — flashcards for patterns & tricks (exported to Anki) + - `notes.org` — deep implementation notes with explanations (exported to Anki) + - `suggestions.org` — pattern reference for quick lookup (not exported) + +4. **Study flow** — open roadmap.org, pick a topic, pick a problem, follow the Notes link, solve it, mark it DONE in both places. ## File Layout @@ -24,7 +29,10 @@ org/study_deck_02/ ├── AGENTS.md ← you are here ├── roadmap.org ← generated by leetcode/extract.mjs ├── toolkit/ -│ └── tricks.org ← common patterns & templates +│ ├── tricks.org ← flashcards for patterns & tricks +│ ├── notes.org ← deep implementation notes +│ ├── suggestions.org ← pattern reference (not exported) +│ └── images/ ← diagrams, screenshots └── dsa/ ├── arrays-hashing/ │ ├── 0217-contains-duplicate.org diff --git a/org/study_deck_02/dsa/arrays-hashing/0001-two-sum.org b/org/study_deck_02/dsa/arrays-hashing/0001-two-sum.org index f1a3fb7..6bb54ec 100644 --- a/org/study_deck_02/dsa/arrays-hashing/0001-two-sum.org +++ b/org/study_deck_02/dsa/arrays-hashing/0001-two-sum.org @@ -57,6 +57,12 @@ Write your approach here. #+begin_src python class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: + sb = {} + for xi, x in enumerate(nums): + want = target - x; + if want in sb: + return sb[want], xi + sb[x] = xi #+end_src ** TODO C++ diff --git a/org/study_deck_02/dsa/arrays-hashing/0347-top-k-frequent-elements.org b/org/study_deck_02/dsa/arrays-hashing/0347-top-k-frequent-elements.org index da283d5..8448016 100644 --- a/org/study_deck_02/dsa/arrays-hashing/0347-top-k-frequent-elements.org +++ b/org/study_deck_02/dsa/arrays-hashing/0347-top-k-frequent-elements.org @@ -40,9 +40,11 @@ Given an integer array ~nums~ and an integer ~k~, return /the/ ~k~ /most frequen Write your approach here. ** TODO Python -#+begin_src python +#+begin_src python :lc-problem 347 :lc-lang python3 class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: + from collections import Counter + return [n for n, _ in Counter(nums).most_common(k)] #+end_src ** TODO C++ diff --git a/org/study_deck_02/dsa/arrays-hashing/1408-string-matching-in-an-array.org b/org/study_deck_02/dsa/arrays-hashing/1408-string-matching-in-an-array.org index 2f001f9..c9f4664 100644 --- a/org/study_deck_02/dsa/arrays-hashing/1408-string-matching-in-an-array.org +++ b/org/study_deck_02/dsa/arrays-hashing/1408-string-matching-in-an-array.org @@ -52,10 +52,40 @@ Write your approach here. ** TODO Python #+begin_src python +from collections import defaultdict as dd class Solution: def stringMatching(self, words: List[str]) -> List[str]: + words = reversed(sorted(words)) + def squash(word, trie): + lst = [] + for c in word: + lst.append([trie, '']) + for i in range(len(lst)): + lst[i][0] = lst[i][0][c] + lst[i][1] += c + if not lst[i][0]['ads']: + lst[i][0]['ads'] = {lst[i][1]: [word]} + else: + lst[i][0]['ads'][lst[i][1]].append(word) + def in_trie(word, trie): + for c in word: + if c not in trie: + return [] + trie = trie[c] + return [(word, bw) for bw in trie['ads'][word]] + trie_maker = lambda: dd(trie_maker) + trie = trie_maker() + ans = [] + for s in words: + ans += in_trie(s, trie) + squash(s, trie) + return ans + + #+end_src +** + ** TODO C++ #+begin_src cpp class Solution { diff --git a/org/study_deck_02/roadmap.org b/org/study_deck_02/roadmap.org index 660c325..b450792 100644 --- a/org/study_deck_02/roadmap.org +++ b/org/study_deck_02/roadmap.org @@ -1,7 +1,7 @@ #+TITLE: NeetCode Roadmap #+ANKI_DECK: study_deck_02 #+DATE: 2026-06-01 -#+TODO: TODO DONE +#+TODO: TODO TOO_EASY DONE #+STARTUP: overview Source: [[https://neetcode.io/roadmap][neetcode.io/roadmap]] @@ -32,7 +32,7 @@ Notes: [[file:dsa/arrays-hashing/0217-contains-duplicate.org]] *** DONE Python *** DONE C++ Notes: [[file:dsa/arrays-hashing/0242-valid-anagram.org]] -** TODO 2678. Number of Senior Citizens :easy: +** TOO_EASY 2678. Number of Senior Citizens :easy: :PROPERTIES: :LEETCODE: [[https://leetcode.com/problems/number-of-senior-citizens/][Problem]] :CPP: [[https://github.com/neetcode-gh/leetcode/blob/main/cpp/2678-number-of-senior-citizens.cpp][Solution]] @@ -51,7 +51,7 @@ Notes: [[file:dsa/arrays-hashing/2678-number-of-senior-citizens.org]] :VIDEO: [[https://youtube.com/watch?v=KLlXCFG5TnA][Watch]] :END: -*** TODO Python +*** DONE Python *** TODO C++ Notes: [[file:dsa/arrays-hashing/0001-two-sum.org]] ** TODO 1408. String Matching in an Array :easy: diff --git a/org/study_deck_02/toolkit/notes.org b/org/study_deck_02/toolkit/notes.org index c279c34..1bd3f57 100644 --- a/org/study_deck_02/toolkit/notes.org +++ b/org/study_deck_02/toolkit/notes.org @@ -25,3 +25,116 @@ public: } }; #+end_src + +** Why ~std::array~ over C-style arrays? + +*** Type safety +- ~std::array~ carries its size in the type system +- C-style ~int freq[26]~ decays to ~int*~ when passed to functions — size info lost +- ~std::array~ knows its size: ~freq.size()~ always returns 26 + +*** Value semantics +- ~std::array~ can be copied, assigned, returned from functions like any value +- C arrays decay to pointers, can't be assigned: +#+begin_src cpp +int a[5] = {1,2,3,4,5}; +int b[5]; +b = a; // ERROR: array type 'int[5]' is not assignable + +std::array sa = {1,2,3,4,5}; +std::array sb; +sb = sa; // OK: copies all elements +#+end_src + +*** No pointer decay +- C arrays silently decay to ~T*~ in many contexts — source of bugs +- ~std::array~ never decays; pass by reference explicitly: ~void f(const std::array& a)~ + +*** Bounds checking (optional) +- ~.at(i)~ throws ~std::out_of_range~ on bad index +- ~[i]~ is unchecked (same as C array) — zero overhead if you want it +- C arrays have no checked access option + +*** Works with STL algorithms +- ~std::all_of~, ~std::sort~, ~std::find~ etc. work directly on ~std::array~ +- C arrays need explicit begin/end: ~std::all_of(std::begin(arr), std::end(arr), ...)~ +- ~std::array~ has ~.begin()~, ~.end()~, ~.size()~ + +*** Cons of ~std::array~ +- Slightly more verbose syntax: ~std::array~ vs ~int[26]~ +- Template parameter required — can't use runtime size (use ~std::vector~ then) +- Compile-time dependency: size must be constexpr + +** Why ~std::all_of~? + +*** Declarative intent +- "All elements satisfy predicate" — reads like English +- vs manual loop: ~for (int i=0; i<26; i++) if (freq[i]!=0) return false;~ — imperative, more mental parsing + +*** Zero overhead +- Compiles to same machine code as hand-written loop +- Optimizer inlines the lambda, unrolls if beneficial +- No performance penalty vs manual loop + +*** Composability +- Can chain with other STL: ~std::any_of~, ~std::none_of~, ~std::count_if~ +- Lambda can be arbitrarily complex without changing the loop structure +- Easy to swap predicate without restructuring code + +*** Cons +- Slightly harder to debug (breakpoint inside lambda vs explicit loop) +- For trivial checks, manual loop may be more readable to some +- Requires ~~ include + +** How does the compiler know 26 is okay? + +*** Compile-time constant +- 26 is a literal — known at compile time +- Template parameter ~N~ in ~std::array~ requires constexpr +- Compiler sees: "allocate space for 26 ints right here, right now" + +*** Where does the memory live? + +~std::array~ is an aggregate containing ~int data[26]~. +- If local variable → *stack* allocation +- If global/static → *data/bss* segment +- If member of class → wherever the object lives + +Stack allocation is just moving the stack pointer: +#+begin_src asm +sub rsp, 104 ; 26 * 4 bytes = 104 bytes +; freq is now at [rsp], zero-initialized by {} +#+end_src + +*** Zero-initialization +- ~std::array freq{};~ — value-initialization, all zeros +- Compiler may emit ~memset~ or just zero the stack frame +- C-style ~int freq[26];~ is *uninitialized* — garbage values +- C-style ~int freq[26] = {};~ or ~int freq[26]{};~ also zero-initializes + +*** Size is part of the type +- ~std::array~ and ~std::array~ are *different types* +- Can't accidentally mix them — type error at compile time +- C arrays: ~void f(int a[26])~ actually becomes ~void f(int* a)~ — size lost + +*** Compile-time evaluation +- ~freq.size()~ is constexpr 26 — no runtime overhead +- Loop ~for (int i = 0; i < 26; i++)~ — compiler may unroll entirely +- With ~constexpr~ arrays, entire computation can happen at compile time + +** What about ~std::unordered_map~? + +When alphabet is *not* bounded (Unicode, arbitrary keys): +- ~std::map~ — O(log n) per op, ordered, tree-based +- ~std::unordered_map~ — O(1) average, hash table, unordered + +For lowercase a-z, neither beats array: +- Array: ~freq[c - 'a']~ — direct index, one memory access +- Map/unordered_map: hash + probe/compare — multiple accesses, branches + +** Questions for later +- How does the stack pointer move for arrays of different sizes? +- What's the alignment requirement for ~std::array~? +- Can ~std::array~ be ~constexpr~? +- What about ~std::array~ vs ~std::vector~ for dynamic sizes? +- How does the optimizer decide to unroll the ~all_of~ loop?