fix(post): fetch code lazily
This commit is contained in:
parent
ee3a3b61a2
commit
ed83255604
10 changed files with 209 additions and 172 deletions
|
|
@ -115,44 +115,7 @@
|
|||
operations. The minimum/maximum element must be found via a linear
|
||||
scan in \(O(n)\) time, certainly far from optimal.
|
||||
</p>
|
||||
<pre><code class="language-cpp">#include <algorithm>
|
||||
#include <deque>
|
||||
#include <stdexcept>
|
||||
|
||||
class ExtremaCircularBuffer {
|
||||
public:
|
||||
ExtremaCircularBuffer(size_t capacity) : capacity(capacity) {}
|
||||
|
||||
void push_back(double value) {
|
||||
if (prices.size() == capacity) {
|
||||
prices.pop_front();
|
||||
}
|
||||
|
||||
prices.push_back(value);
|
||||
}
|
||||
|
||||
void pop_front() {
|
||||
if (prices.empty()) {
|
||||
throw std::out_of_range("Cannot pop_front() from empty buffer");
|
||||
}
|
||||
|
||||
prices.pop_front();
|
||||
}
|
||||
|
||||
size_t size() const { return prices.size(); }
|
||||
|
||||
double get() const {
|
||||
if (prices.empty()) {
|
||||
throw std::out_of_range("Cannot find max() of empty buffer");
|
||||
}
|
||||
|
||||
return *std::max_element(prices.begin(), prices.end());
|
||||
}
|
||||
|
||||
private:
|
||||
std::deque<double> prices;
|
||||
size_t capacity;
|
||||
};</code></pre>
|
||||
<div class="code" data-file="naive.cpp"</div>
|
||||
</div>
|
||||
<h3>optimizing the approach</h3>
|
||||
<div class="problem-content">
|
||||
|
|
@ -174,9 +137,7 @@ private:
|
|||
<a
|
||||
target="blank"
|
||||
href="https://en.cppreference.com/w/cpp/container/map"
|
||||
><span class="inline-code"
|
||||
><code>std::map<double, size_t></code></span
|
||||
></a
|
||||
>std::map</a
|
||||
>
|
||||
allows us to do all of this.
|
||||
</p>
|
||||
|
|
@ -184,62 +145,7 @@ private:
|
|||
Now, we can access extrema instantly. Insertion and deletion take
|
||||
\(O(log(n))\) time thanks to the map—but we can do better.
|
||||
</p>
|
||||
<pre><code class="language-cpp">#include <deque>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
class ExtremaCircularBuffer {
|
||||
public:
|
||||
ExtremaCircularBuffer(size_t capacity) : capacity(capacity) {}
|
||||
|
||||
void push_back(double value) {
|
||||
if (prices.size() == capacity) {
|
||||
double front = prices.front();
|
||||
|
||||
if (--sorted_prices[front] == 0)
|
||||
sorted_prices.erase(front);
|
||||
prices.pop_front();
|
||||
}
|
||||
|
||||
prices.push_back(value);
|
||||
++sorted_prices[value];
|
||||
}
|
||||
|
||||
void pop_front() {
|
||||
if (prices.empty()) {
|
||||
throw std::out_of_range("Cannot pop_front() from empty buffer");
|
||||
}
|
||||
|
||||
double front = prices.front();
|
||||
|
||||
if (--sorted_prices[front] == 0)
|
||||
sorted_prices.erase(front);
|
||||
prices.pop_front();
|
||||
}
|
||||
|
||||
size_t size() const { return prices.size(); }
|
||||
|
||||
double get_max() const {
|
||||
if (prices.empty()) {
|
||||
throw std::out_of_range("Cannot find max() of empty buffer");
|
||||
}
|
||||
|
||||
return sorted_prices.rbegin()->first;
|
||||
}
|
||||
|
||||
double get_min() const {
|
||||
if (prices.empty()) {
|
||||
throw std::out_of_range("Cannot find min() of empty buffer");
|
||||
}
|
||||
|
||||
return sorted_prices.begin()->first;
|
||||
}
|
||||
|
||||
private:
|
||||
std::deque<double> prices;
|
||||
std::map<double, size_t> sorted_prices;
|
||||
size_t capacity;
|
||||
};</code></pre>
|
||||
<div class="code" data-file="map.cpp"></div>
|
||||
</div>
|
||||
<h3>monotonic <s>queues</s> deques</h3>
|
||||
<div class="problem-content">
|
||||
|
|
@ -298,71 +204,7 @@ private:
|
|||
once; across a sequence of \(n\) operations, \(n\) total \(O(1)\)
|
||||
operations will be executed).
|
||||
</p>
|
||||
<pre><code class="language-cpp">#include <deque>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
class ExtremaCircularBuffer {
|
||||
public:
|
||||
explicit ExtremaCircularBuffer(size_t capacity) : capacity(capacity) {}
|
||||
|
||||
void push_back(double value) {
|
||||
if (prices.size() == capacity) {
|
||||
double front_value = prices.front();
|
||||
pop_max(front_value);
|
||||
prices.pop_front();
|
||||
}
|
||||
|
||||
prices.push_back(value);
|
||||
push_max(value);
|
||||
}
|
||||
|
||||
void pop_front() {
|
||||
if (prices.empty()) {
|
||||
throw std::out_of_range("Cannot pop_front() from empty buffer");
|
||||
}
|
||||
|
||||
double front_value = prices.front();
|
||||
pop_max(front_value);
|
||||
prices.pop_front();
|
||||
}
|
||||
|
||||
size_t size() const { return prices.size(); }
|
||||
|
||||
double get_max() const {
|
||||
if (prices.empty()) {
|
||||
throw std::out_of_range("Cannot find max() of empty buffer");
|
||||
}
|
||||
|
||||
return maxs.front().first;
|
||||
}
|
||||
|
||||
private:
|
||||
void push_max(double value) {
|
||||
size_t popped = 0;
|
||||
|
||||
while (!maxs.empty() && maxs.back().first < value) {
|
||||
popped += maxs.back().second + 1;
|
||||
maxs.pop_back();
|
||||
}
|
||||
|
||||
maxs.emplace_back(value, popped);
|
||||
}
|
||||
|
||||
void pop_max(double value) {
|
||||
size_t popped = maxs.front().second;
|
||||
|
||||
if (popped == 0) {
|
||||
maxs.pop_front();
|
||||
} else {
|
||||
--maxs.front().second;
|
||||
}
|
||||
}
|
||||
|
||||
std::deque<double> prices;
|
||||
std::deque<std::pair<double, size_t>> maxs;
|
||||
size_t capacity;
|
||||
};</code></pre>
|
||||
<div class="code" data-file="monotonic.cpp"></div>
|
||||
<h3>further improvements</h3>
|
||||
<ol>
|
||||
<li>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue