From 548f860cd45c5950a681f8e264e216d5284d3033 Mon Sep 17 00:00:00 2001
From: "Brady J. Garvin" <bgarvin@cse.unl.edu>
Date: Tue, 1 Nov 2022 12:00:12 -0500
Subject: [PATCH] Designed and implemented mergesort and quickmedian.

---
 divide-and-conquer/notes.md                   | 73 +++++++++++--------
 .../src/features/median/kthSmallest.js        | 12 ++-
 .../src/features/sorting/sorting.js           | 22 +++++-
 3 files changed, 75 insertions(+), 32 deletions(-)

diff --git a/divide-and-conquer/notes.md b/divide-and-conquer/notes.md
index cdbfed9..45ab4df 100644
--- a/divide-and-conquer/notes.md
+++ b/divide-and-conquer/notes.md
@@ -48,19 +48,19 @@ Problem: Sort a list in Θ(n log n) time.
 
 ```
             In:  [8, 7, 6, 9, 5]
-            Out: […, …, …, …, …]
+            Out: [5, 6, 7, 8, 9]
                 /          \
                /            \
-    In:  […]                 In:  […]
-    Out: […]                 Out: […]
+    In:  [8, 7]              In:  [6, 9, 5]
+    Out: [7, 8]              Out: [5, 6, 9]
        /  \                    /      \
       /    \                  /        \
-In:  […]    In:  […]    In:  […]        In: […]
-Out: […]    Out: […]    Out: […]        Out: […]
+In:  [8]    In:  [7]    In:  [6]        In:  [9, 5]
+Out: [8]    Out: [7]    Out: [6]        Out: [5, 9]
                                            /  \
                                           /    \
-                                    In:  […]    In:  […]
-                                    Out: […]    Out: […]
+                                    In:  [9]    In:  [5]
+                                    Out: [9]    Out: [5]
 ```
 
 ## Analysis
@@ -69,14 +69,14 @@ Out: […]    Out: […]    Out: […]        Out: […]
 
     T(n) = T(⌊n/2⌋) + T(⌈n/2⌉) + Θ(n)   for n ≫ 0
     T(n) ≈ 2T(n/2) + Θ(n)               for n ≫ 0
-    T(n) = Θ(⋯)
+    T(n) = Θ(n log n)
 
 *   Uneven split:
 
     T(n) = T(n - 1) + T(1) + Θ(n)   for n ≫ 0
     T(n) = T(n - 1) + Θ(1) + Θ(n)   for n ≫ 0
     T(n) = T(n - 1) + Θ(n)          for n ≫ 0
-    T(n) = Θ(⋯)
+    T(n) = Θ(n²)
 
 --------------------------------------------------------------------------------
 
@@ -96,11 +96,11 @@ Problem: Find the median of an odd-length list in average-case Θ(n) time.  Use
 
 ```
             In:  [8, 7, 6, 9, 5]
-            Out: …
+            Out: ????
                 /          \
                /            \
-    In:  […]                 In:  […]
-    Out: …                   Out: …
+    In:  [8, 7]              In:  [6, 9, 5]
+    Out: 7.5                 Out: 6
 ```
 
 *   Option A: We are missing information from the recursive calls.  Add output(s) so that they can return that information.
@@ -108,15 +108,15 @@ Problem: Find the median of an odd-length list in average-case Θ(n) time.  Use
 
 ## Design (second attempt)
 
-*   More generally, we want …, so we add an input `k`:
+*   More generally, we want kth smallest element, so we add an input `k`:
 
 ```
             In:  [8, 7, 6, 9, 5], k = 2
             Out: …
                 /          \
                /            \
-    In:  […], k = 2          In:  […], k = 0
-    Out: …                   Out: …
+    In:  [8, 7], k = 2       In:  [6, 9, 5], k = 0
+    Out: ????                Out: 5
 ```
 
 ## Partitioning
@@ -131,24 +131,39 @@ Problem: Find the median of an odd-length list in average-case Θ(n) time.  Use
 
 ```
     In:  [8, 7, 6, 9, 5], k = 2
-    In:  […], k = 2
-    In:  […], k = 2
-    Split: […], …, […]
-    Out: …
+          *
+                   i
+                      j
+    In:  [8, 7, 6, 5, 9], k = 2
+          *
+                      i (crossed)
+                   j
+          i
+    In:  [5, 7, 6, 8, 9], k = 2
+    Split: [5, 7, 6], 8, [9]
+    Out: 7
      |
      |
      |
-    In:  […], k = …
-    In:  […], k = …
-    Split: […], …, […]
-    Out: …
+    In:  [5, 7, 6], k = 2
+          *
+             i (crossed)
+          j
+          i
+    In:  [5, 7, 6], k = 2
+    Split: [], 5, [7, 6]
+    Out: 7
      |
      |
      |
-    In:  […], k = …
-    In:  […], k = …
-    Split: […], …, […]
-    Out: …
+    In:  [7, 6], k = 1
+          *
+                i (crossed)
+             j
+          i
+    In:  [6, 7], k = 1
+    Split: [6], 7, []
+    Out: 7
 ```
 
 ## Analysis
@@ -156,9 +171,9 @@ Problem: Find the median of an odd-length list in average-case Θ(n) time.  Use
 *   Uneven split:
 
     T(n) = T(n - 1) + Θ(n)   for n ≫ 0
-    T(n) = Θ(⋯)
+    T(n) = Θ(n²)
 
 *   Even split:
 
     T(n) ≈ T(n/2) + Θ(n)               for n ≫ 0
-    T(n) = Θ(⋯)
+    T(n) = Θ(n)
diff --git a/divide-and-conquer/src/features/median/kthSmallest.js b/divide-and-conquer/src/features/median/kthSmallest.js
index 7125d1f..26e87bb 100644
--- a/divide-and-conquer/src/features/median/kthSmallest.js
+++ b/divide-and-conquer/src/features/median/kthSmallest.js
@@ -31,5 +31,15 @@ export function kthSmallest(sequence, k) {
     k >= 0 && k < sequence.length,
     'Tried to find the kth smallest element when k is out of bounds.',
   );
-  return sequence[0]; // TODO: stub
+  if (sequence.length < 2) {
+    return sequence[0];
+  }
+  const [left, pivot, right] = partition(sequence);
+  if (k === left.length) {
+    return pivot;
+  }
+  if (k < left.length) {
+    return kthSmallest(left, k);
+  }
+  return kthSmallest(right, k - left.length - 1);
 }
diff --git a/divide-and-conquer/src/features/sorting/sorting.js b/divide-and-conquer/src/features/sorting/sorting.js
index bca3d88..10eb765 100644
--- a/divide-and-conquer/src/features/sorting/sorting.js
+++ b/divide-and-conquer/src/features/sorting/sorting.js
@@ -1,7 +1,25 @@
 function merge(left, right) {
-  return []; // TODO: stub
+  const results = [];
+  let i = 0;
+  let j = 0;
+  while (i < left.length || j < right.length) {
+    if (j >= right.length || (i < left.length && left[i] < right[j])) {
+      results.push(left[i]);
+      ++i;
+    } else {
+      results.push(right[j]);
+      ++j;
+    }
+  }
+  return results;
 }
 
 export function sort(list) {
-  return list; // TODO: stub
+  if (list.length < 2) {
+    return list;
+  }
+  const middleIndex = Math.floor(list.length / 2);
+  const left = sort(list.slice(0, middleIndex));
+  const right = sort(list.slice(middleIndex, list.length));
+  return merge(left, right);
 }
-- 
GitLab