From 1609a58c3c1f3858f8d67a1c8c861eac1174d0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Vo=C3=9F?= Date: Tue, 7 Jul 2015 10:39:57 +0200 Subject: [PATCH] Rework example 7 and provide an alternative way of solving the problem. --- c++/Chapter 11/Chapter11_7.cpp | 104 ++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 33 deletions(-) diff --git a/c++/Chapter 11/Chapter11_7.cpp b/c++/Chapter 11/Chapter11_7.cpp index f7aea593..2dccb4db 100644 --- a/c++/Chapter 11/Chapter11_7.cpp +++ b/c++/Chapter 11/Chapter11_7.cpp @@ -1,51 +1,89 @@ +#include #include +#include +#include #include + using namespace std; -struct htWt { +struct Person { int height, weight; }; -void sortHeight(htWt arr[], int n) { - for (int i=0; iarr[j+1].height) { - htWt tmp = arr[j]; - arr[j] = arr[j+1]; - arr[j+1] = tmp; - } +bool operator<(const Person& lhs, const Person& rhs) { + return std::tie(lhs.height, lhs.weight) < std::tie(rhs.height, rhs.weight); +} + +// Time complexity: O(n + n * log(n)) = O(n * log(n)) +// Space complexity: O(1) +template +unsigned int CalculateTower(std::vector& persons) { + make_heap(persons.begin(), persons.end()); + auto rit = persons.end(); + unsigned int result = 0; + Person current{std::numeric_limits::max(), std::numeric_limits::max()}; + + while (rit >= persons.begin()) { + if (persons.front() < current) { + current = persons.front(); + result++; } + + pop_heap(persons.begin(), rit); + rit = prev(rit); } + + return result; } -int getIncreasingSequence(htWt arr[], int n) { - sortHeight(arr, n); - vector > wt; - for (int i=0; i= wt[j].back()) { - flag = false; - wt[j].push_back(arr[i].weight); +// Time complexity: O(n^2) +// Space complexity: O(n) +template> +unsigned int LongestIncreasingSubsequence(const std::vector& values, Comparator comp = Comparator()) { + vector l(values.size(), 1); + unsigned int best = 0; + for (int i = 1; i < values.size(); i++) { + unsigned int max = 0; + for (int j = i - 1; j >= 0; j--) { + if (comp(values[j], values[i])) { + max = std::max(max, l[j]); } } - if (flag) { - vector v; - v.push_back(arr[i].weight); - wt.push_back(v); - } + l[i] = ++max; + best = std::max(best, max); } - int max = 0; - for (int i=0; i persons{{12, 13}, {11, 15}, {9, 20}, {20, 20}, {40, 21}, {8, 42}}; + + // We calculate the maximum height of a tower of persons by relying on a max-heap, + // popping persons of the heap onto the tower if the current max element in the heap + // is strictly smaller than the current top-most person in the tower. If it is not strictly + // smaller, we just drop the person as they are "as good as"/"incomparable to" the person + // already standing on top of the tower. Please note that this works because we are not maximizing + // the total height of the tower, but only the number of people being involved in it. + { + vector cpersons = persons; + cout << "With heap: " << CalculateTower(cpersons) << "\n"; + } + // We are not altering the original sequence as in the original problem statement for + // the longest increasing subsequence problem. For the example setup presented here, + // the longest strictly increasing subsequence is 3. + { + cout << "Without sorting: " << LongestIncreasingSubsequence(persons) << "\n"; + } + // We are mutating the original sequence of values here, requiring O(n log(n)) to do so. + // Alternatively, we could just rely on a heap to achieve the same functionality. + { + vector cpersons(persons); + sort(cpersons.begin(), cpersons.end(), [](const Person& lhs, const Person& rhs) { + return lhs.height < rhs.height; + }); + cout << "With sorting by height: " << LongestIncreasingSubsequence(cpersons) << "\n"; + } return 0; -} \ No newline at end of file +}