From 2663b97c55ce35fb603944ba0c37a111ebea4ddf Mon Sep 17 00:00:00 2001 From: Joshua Potter Date: Fri, 23 Feb 2024 19:43:29 -0700 Subject: [PATCH] Add merge sort and more notes on floors/ceilings. --- .../plugins/obsidian-to-anki-plugin/data.json | 12 +- notes/_journal/2024-02-23.md | 6 +- notes/algebra/floor-ceiling.md | 32 ++++ notes/algorithms/images/merge-sort.gif | Bin 0 -> 7854 bytes notes/algorithms/index.md | 97 +++++++++++ notes/algorithms/sorting/merge-sort.md | 156 ++++++++++++++++++ 6 files changed, 296 insertions(+), 7 deletions(-) create mode 100644 notes/algorithms/images/merge-sort.gif create mode 100644 notes/algorithms/sorting/merge-sort.md diff --git a/notes/.obsidian/plugins/obsidian-to-anki-plugin/data.json b/notes/.obsidian/plugins/obsidian-to-anki-plugin/data.json index a41ce05..e3651d5 100644 --- a/notes/.obsidian/plugins/obsidian-to-anki-plugin/data.json +++ b/notes/.obsidian/plugins/obsidian-to-anki-plugin/data.json @@ -79,10 +79,11 @@ "lattice-path-chessboard.png", "lattice-path-chessboard-colored.png", "lattice-path-before-recurrence.png", - "lattice-path-after-recurrence.png" + "lattice-path-after-recurrence.png", + "merge-sort.gif" ], "File Hashes": { - "algorithms/index.md": "a5ff7313f71777f1f3536e27dd9894fa", + "algorithms/index.md": "cd7c7ba91fb2f961c9f2437777e8e2ac", "algorithms/sorting/index.md": "2d5a18a3079d96fa9e3d4289181a8b6c", "algorithms/sorting/insertion-sort.md": "00e4edb132d473b0516fde3307ebae30", "bash/index.md": "3dfeb538d781e4645e3aaaf32beb1034", @@ -166,7 +167,7 @@ "_journal/2024-02/2024-02-14.md": "aa009f9569e175a8104b0537ebcc5520", "_journal/2024-02-16.md": "5cc129254afd553829be3364facd23db", "_journal/2024-02/2024-02-15.md": "16cb7563d404cb543719b7bb5037aeed", - "algebra/floor-ceiling.md": "e9f905f5ec01921e0f19afe8732fb38b", + "algebra/floor-ceiling.md": "828b11e642d6803a740b58f27ff047cf", "algebra/index.md": "90b842eb694938d87c7c68779a5cacd1", "algorithms/binary-search.md": "08cb6dc2dfb204a665d8e8333def20ca", "_journal/2024-02-17.md": "7c37cb10515ed3d2f5388eaf02a67048", @@ -189,12 +190,13 @@ "algebra/radices.md": "0fcd901c798eaed8075ff1375e2429dd", "_journal/2024-02-22.md": "e01f1d4bd2f7ac2a667cdfd500885a2a", "_journal/2024-02/2024-02-21.md": "f423137ae550eb958378750d1f5e98c7", - "_journal/2024-02-23.md": "75eec3feffa90a219de77151771fe3fe", + "_journal/2024-02-23.md": "219ce9ad15a8733edd476c97628b71fd", "_journal/2024-02/2024-02-22.md": "312e55d57868026f6e80f7989a889c2b", "c17/strings.md": "bbe8983602adbeb38eff214beddedd84", "c17/index.md": "78576ee41d0185df82c59999142f4edb", "c17/escape-sequences.md": "ebc63c6cdfbe60bbc2708c1b0c8da8bb", - "c17/declarations.md": "46b135d583a992991c889d518fec1c0f" + "c17/declarations.md": "46b135d583a992991c889d518fec1c0f", + "algorithms/sorting/merge-sort.md": "f66f482e5bd551c765fcba564c938d67" }, "fields_dict": { "Basic": [ diff --git a/notes/_journal/2024-02-23.md b/notes/_journal/2024-02-23.md index 0bd53ec..e33e2a1 100644 --- a/notes/_journal/2024-02-23.md +++ b/notes/_journal/2024-02-23.md @@ -7,7 +7,7 @@ title: "2024-02-23" - [ ] Sheet Music (10 min.) - [x] OGS (1 Life & Death Problem) - [ ] Korean (Read 1 Story) -- [ ] Interview Prep (1 Practice Problem) +- [x] Interview Prep (1 Practice Problem) - [x] Log Work Hours (Max 3 hours) * 101weiqi (serial numbers) @@ -19,4 +19,6 @@ title: "2024-02-23" * Q-9107 * Read about extension and truncation of integral values using unsigned and two's-complement encoding. * Read through last sections of "Discrete Mathematics: An Open Introduction"'s first chapter. - * I took a few little notes but I didn't pay as close attention to these sections as others. \ No newline at end of file + * I took a few notes but didn't pay as close attention to these sections as others. +* Leetcode [Decode Ways](https://leetcode.com/problems/decode-ways/solutions/). +* Practiced implementing heap sort and quicksort. \ No newline at end of file diff --git a/notes/algebra/floor-ceiling.md b/notes/algebra/floor-ceiling.md index 520d0b9..02c6b73 100644 --- a/notes/algebra/floor-ceiling.md +++ b/notes/algebra/floor-ceiling.md @@ -240,6 +240,22 @@ Reference: Ronald L. Graham, Donald Ervin Knuth, and Oren Patashnik, *Concrete M END%% +%%ANKI +Basic +Given `A[p..q]` and $r = \lfloor (p + q) / 2 \rfloor$, what is the size of `A[p..r]` in terms of $n = q - p + 1$? +Back: $\lceil n / 2 \rceil$. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +Given `A[p..q]` and $r = \lfloor (p + q) / 2 \rfloor$, what is the size of `A[r+1..q]` in terms of $n = q - p + 1$? +Back: $\lfloor n / 2 \rfloor$. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + %%ANKI Basic Given `A[p..q]` and $r = \lceil (p + q) / 2 \rceil$, how does the size of `A[p..r-1]` compare to `A[r..q]`? @@ -248,6 +264,22 @@ Reference: Ronald L. Graham, Donald Ervin Knuth, and Oren Patashnik, *Concrete M END%% +%%ANKI +Basic +Given `A[p..q]` and $r = \lceil (p + q) / 2 \rceil$, what is the size of `A[r..q]` in terms of $n = q - p + 1$? +Back: $\lceil n / 2 \rceil$. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +Given `A[p..q]` and $r = \lceil (p + q) / 2 \rceil$, what is the size of `A[p..r-1]` in terms of $n = q - p + 1$? +Back: $\lfloor n / 2 \rfloor$. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + %%ANKI Basic Given `A[p..q]` and $r = \lfloor (p + q) / 2 \rfloor$, how does the size of `A[p..r-1]` compare to `A[r..q]`? diff --git a/notes/algorithms/images/merge-sort.gif b/notes/algorithms/images/merge-sort.gif new file mode 100644 index 0000000000000000000000000000000000000000..4eb3353953031cbf31f69d5163079c0dd6c310e6 GIT binary patch literal 7854 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 L>L2lyMwtH}eT~{t literal 0 HcmV?d00001 diff --git a/notes/algorithms/index.md b/notes/algorithms/index.md index 6174075..ddb111b 100644 --- a/notes/algorithms/index.md +++ b/notes/algorithms/index.md @@ -1,5 +1,102 @@ --- title: Algorithms +TARGET DECK: Obsidian::STEM +FILE TAGS: algorithm tags: - algorithm --- + +## Overview + +An **incremental** approach to algorithm design involves acting on a single element at a time. In contrast, the **divide-and-conquer** approach breaks problems into subproblems that are easier to solve. + +%%ANKI +Basic +What does an incremental approach to algorithm design refer to? +Back: An algorithm that acts on a single element at a time. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What does a divide-and-conquer approach to algorithm design refer to? +Back: An algorithm that breaks a problem into similar but simpler subproblems. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What does it mean for a divide-and-conquer algorithm to "bottom out"? +Back: An input that cannot (or should not) be divided any further is encountered. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +In the context of algorithms, what does a "sentinel" refer to? +Back: A special value used to simplify code. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Cloze +Insertion sort is to an {incremental} design approach whereas merge sort is to a {divide-and-conquer} design approach. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What ideas does the term "divide-and-conquer" invoke? +Back: Breaking a problem into subproblems that are easier to solve. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +According to Cormen et al., what three steps do divide-and-conquer algorithms take? +Back: Divide, conquer, and combine. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is the "divide" step of a divide-and-conquer algorithm? +Back: Breaking the problem into smaller instances of the same problem. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is the "conquer" step of a divide-and-conquer algorithm? +Back: Solving subproblems recursively or, if small enough, in a straightforward manner. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is the "combine" step of a divide-and-conquer algorithm? +Back: Manipulating solutions to smaller problems into a solution for the original problem. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is a running time recurrence? +Back: A formula that describes overall running time in terms of running time on smaller inputs. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +## References + +* Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). \ No newline at end of file diff --git a/notes/algorithms/sorting/merge-sort.md b/notes/algorithms/sorting/merge-sort.md new file mode 100644 index 0000000..01e1412 --- /dev/null +++ b/notes/algorithms/sorting/merge-sort.md @@ -0,0 +1,156 @@ +--- +title: Merge Sort +TARGET DECK: Obsidian::STEM +FILE TAGS: algorithm::sorting +tags: + - algorithm + - sorting +--- + +## Overview + +Property | Value +----------- | -------- +Best Case | $\Omega(n\lg{n})$ +Worst Case | $O(n\lg{n})$ +Avg. Case | $O(n\lg{n})$ +Aux. Memory | - +Stable | - +Adaptive | - + +![[merge-sort.gif]] + +%%ANKI +Basic +What does the term "merge" in merge sort refer to? +Back: The primary operation used to combine array halves. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is merge sort's best case runtime? +Back: $\Omega(n\lg{n})$ +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is merge sort's worst case runtime? +Back: $O(n\lg{n})$ +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is merge sort's average case runtime? +Back: $O(n\lg{n})$ +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is the "divide" step of merge sort? +Back: Divide the input array into two subarrays of half size. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is the "conquer" step of merge sort? +Back: Call merge sort on the "divide"-step's two subarrays. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What is the "combine" step of merge sort? +Back: Merge the subarrays sorted after the "conquer" step. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +When does merge sort "bottom out"? +Back: When the sequence to be sorted has length 1 or less. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +```c +static void merge(int i, int mid, int j, int *A) { + int si = mid - i + 1; + int sj = j - (mid + 1) + 1; + + int *L = malloc(sizeof(int) * (si + 1)); + int *R = malloc(sizeof(int) * (sj + 1)); + + L[si] = INT_MAX; + R[sj] = INT_MAX; + + for (int k = 0; k < si; ++k) { + L[k] = A[i + k]; + } + for (int k = 0; k < sj; ++k) { + R[k] = A[mid + 1 + k]; + } + + int topL = 0, topR = 0; + for (int k = 0; k < j - i + 1; ++k) { + if (L[topL] < R[topR]) { + A[i + k] = L[topL++]; + } else { + A[i + k] = R[topR++]; + } + } + + free(L); + free(R); +} + +void merge_sort(int i, int j, int *A) { + if (j <= i) { + return; + } + int mid = (i + j) / 2; + merge_sort(i, mid, A); + merge_sort(mid + 1, j, A); + merge(i, mid, j, A); +} +``` + +%%ANKI +Basic +Where in merge sort's implementation are sentinels useful? +Back: As the last elements of the two arrays to combine. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What sentinel values are typically used in merge sort's "merge" operation? +Back: $\infty$ or the record type's equivalent. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +%%ANKI +Basic +What sorting algorithm does the following demonstrate? +![[merge-sort.gif]] +Back: Merge sort. +Reference: Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009). + +END%% + +## References + +* Thomas H. Cormen et al., *Introduction to Algorithms*, 3rd ed (Cambridge, Mass: MIT Press, 2009).