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