diff --git a/cpp/2205/220506.cpp b/cpp/2205/220506.cpp new file mode 100644 index 0000000..b8a36f6 --- /dev/null +++ b/cpp/2205/220506.cpp @@ -0,0 +1,149 @@ +#include +#include +#include +#include + +template +struct ListNode { + T data; + ListNode* prev; + ListNode* next; + + explicit ListNode(T d, ListNode* p = nullptr, ListNode* n = nullptr) : data(std::move(d)), prev(p), next(n) {} + ListNode(ListNode* p, ListNode* n) : prev(p), next(n) {} +}; + +template +struct LinkedList { + unsigned long long size = 0; + ListNode* front = nullptr; + ListNode* rear = nullptr; + + LinkedList() { + front = new ListNode((ListNode*)nullptr, (ListNode*)nullptr); + rear = new ListNode(front, (ListNode*) nullptr); + front->next = rear; + } + + void push_back(T data) { + auto* node = new ListNode(data, rear->prev, rear); + rear->prev = rear->prev->next = node; + ++size; + } + + ListNode* erase(ListNode* node) { + auto ret = node->next; + node->prev->next = node->next; + node->next->prev = node->prev; + delete node; + --size; + return ret; + } + + bool empty() const { + return !size; + } + + ListNode* begin() { + return front->next; + } + + ListNode* end() { + return rear; + } +}; + +/** + * 1209. Remove All Adjacent Duplicates in String II + * You are given a string s and an integer k, a k duplicate removal consists of choosing k adjacent and equal letters from s and removing them, causing the left and the right side of the deleted substring to concatenate together. + * We repeatedly make k duplicate removals on s until we no longer can. + * Return the final string after all such duplicate removals have been made. It is guaranteed that the answer is unique. + */ + +class Solution { +public: + static std::string removeDuplicates(const std::string& s, int k) { + if (s.empty()) + return {}; + + LinkedList> cnt; + { + int c = 1; + char current = *s.c_str(); + for (const char* ptr = s.c_str() + 1; *ptr; ++ptr) { + if (*ptr == current) { + ++c; + continue; + } + cnt.push_back({current, c}); + c = 1; + current = *ptr; + } + cnt.push_back({current, c}); + } + + // Remove & Merge + for (auto ptr = cnt.begin(); ptr != cnt.end();) { + // Now, nothing can be merged. + + // Eliminate at once + ptr->data.second %= k; + + // Check if totally removed + if (ptr->data.second) { + ptr = ptr->next; + continue; + } + + // Totally removed! + // possible to be merged + ptr = cnt.erase(ptr); + if (cnt.empty()) + break; + if (ptr != cnt.begin()) + ptr = ptr->prev; + auto prevPtr = ptr; + ptr = ptr->next; + while (ptr != cnt.end() && prevPtr->data.first == ptr->data.first) { + prevPtr->data.second += ptr->data.second; + ptr = cnt.erase(ptr); + } + + ptr = prevPtr; + } + + std::string ret; + for (auto* ptr = cnt.begin(); ptr != cnt.end(); ptr = ptr->next) { + const auto [ch, n] = ptr->data; + ret.append(n, ch); + } + return ret; + } +}; + +class Stopwatch { +private: + std::chrono::high_resolution_clock::time_point start; +public: + Stopwatch() { + this->start = std::chrono::high_resolution_clock::now(); + } + + ~Stopwatch() { + std::printf("Time elapsed: %.6lf ms\n", std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count() / 1000000.0); + } +}; + +int main() { + std::string arg; + arg.reserve(100000); + for (int i = 0; i < 1923; ++i) + arg += "abcdefghijklmnopqrstuvwxyz"; + for (int i = 0; i < 1923; ++i) + arg += "zyxwvutsrqponmlkjihgfedcba"; + { + Stopwatch s; + std::cout << Solution::removeDuplicates(arg, 2) << "\n"; + } + return 0; +} diff --git a/cpp/2205/CMakeLists.txt b/cpp/2205/CMakeLists.txt index e25e142..d038401 100644 --- a/cpp/2205/CMakeLists.txt +++ b/cpp/2205/CMakeLists.txt @@ -3,4 +3,4 @@ PROJECT(2205) SET(CMAKE_CXX_STANDARD 23) -ADD_EXECUTABLE(2204 220505.cpp) +ADD_EXECUTABLE(2205 220506.cpp)