|
7 | 7 | * https://leetcode.com/problems/reverse-linked-list-ii/
|
8 | 8 | */
|
9 | 9 |
|
10 |
| -#include <bits/stdc++.h> |
11 |
| - |
12 |
| -using namespace std; |
13 |
| - |
14 |
| -/* =========================================================================== |
15 |
| - * Data structures |
16 |
| - * =========================================================================== |
17 |
| - */ |
18 |
| - |
19 |
| -struct Node; |
20 |
| -using NodePtr = shared_ptr<Node>; |
21 |
| -inline NodePtr new_node(int data) { return make_shared<Node>(data); } |
22 |
| - |
23 |
| -struct Node { |
24 |
| - int data = 0; |
25 |
| - NodePtr next = nullptr; |
26 |
| - |
27 |
| - Node(int data) : data(data), next(nullptr) {} |
28 |
| -}; |
29 |
| - |
30 |
| -void list_append(NodePtr &tail, int data) |
31 |
| -{ |
32 |
| - auto node = new_node(data); |
33 |
| - if (tail) tail->next = node; |
34 |
| - tail = node; |
35 |
| -} |
36 |
| - |
37 |
| -/* =========================================================================== |
38 |
| - * Test helpers |
39 |
| - * =========================================================================== |
40 |
| - */ |
41 |
| -class _00_test |
42 |
| -{ |
43 |
| -public: |
44 |
| - _00_test(const string &name) : name(name) {} |
45 |
| - |
46 |
| - string getName(void) const { return name; } |
47 |
| - |
48 |
| - virtual NodePtr reverseBetween(NodePtr head, int start, int end) = 0; |
49 |
| - |
50 |
| -private: |
51 |
| - string name; |
52 |
| -}; |
| 10 | +#include "tests.h" |
| 11 | +#include "linked-lists.h" |
53 | 12 |
|
54 | 13 | /* ===========================================================================
|
55 | 14 | * Algorithms implementation
|
56 | 15 | * ===========================================================================
|
57 | 16 | */
|
58 | 17 |
|
| 18 | +#define _rev_SinglyLinkedList_desc "Singly Linked List" |
| 19 | + |
59 | 20 | /* TC : O(n)
|
60 | 21 | * SC : O(1)
|
61 | 22 | */
|
62 |
| -class _01_iterative : public _00_test |
| 23 | +namespace SinglyLinkedList |
63 | 24 | {
|
64 |
| -public: |
65 |
| - _01_iterative() |
66 |
| - : _00_test("Singly Linked List - reverse between start & end") |
67 |
| - { |
| 25 | +NodePtr reverseBetween(NodePtr head, int start, int end) |
| 26 | +{ |
| 27 | + if (!head || (start == end)) return head; |
| 28 | + NodePtr curr = head, prev = nullptr, next = nullptr; |
| 29 | + int i = 0; |
| 30 | + while (i++ < start - 1 && curr) { |
| 31 | + prev = curr; |
| 32 | + curr = curr->next; |
68 | 33 | }
|
69 |
| - |
70 |
| - NodePtr reverseBetween(NodePtr head, int start, int end) override |
71 |
| - { |
72 |
| - if (!head || (start == end)) return head; |
73 |
| - NodePtr curr = head, prev = nullptr, next = nullptr; |
74 |
| - int i = 0; |
75 |
| - while (i++ < start - 1) { |
76 |
| - prev = curr; |
77 |
| - curr = curr->next; |
78 |
| - } |
79 |
| - NodePtr rprev = prev, rtail = curr; |
80 |
| - while (i++ <= end && curr) { |
81 |
| - next = curr->next; |
82 |
| - curr->next = prev; |
83 |
| - prev = curr; |
84 |
| - curr = next; |
85 |
| - } |
86 |
| - if (rprev) |
87 |
| - rprev->next = prev; |
88 |
| - else |
89 |
| - head = prev; |
90 |
| - if (rtail) rtail->next = curr; |
91 |
| - return head; |
| 34 | + NodePtr rprev = prev, rtail = curr; |
| 35 | + while (i++ <= end && curr) { |
| 36 | + next = curr->next; |
| 37 | + curr->next = prev; |
| 38 | + prev = curr; |
| 39 | + curr = next; |
92 | 40 | }
|
93 |
| -}; |
| 41 | + if (rprev) |
| 42 | + rprev->next = prev; |
| 43 | + else |
| 44 | + head = prev; |
| 45 | + if (rtail) rtail->next = curr; |
| 46 | + return head; |
| 47 | +} |
| 48 | +} // namespace SinglyLinkedList |
94 | 49 |
|
95 | 50 | /* ===========================================================================
|
96 | 51 | * Test code
|
97 | 52 | * ===========================================================================
|
98 | 53 | */
|
99 |
| -string _l2s(NodePtr node) |
100 |
| -{ |
101 |
| - ostringstream out; |
102 |
| - out << "{"; |
103 |
| - for (int i = 0; node; node = node->next) { |
104 |
| - out << (i++ ? ", " : "") << node->data; |
105 |
| - } |
106 |
| - out << "}"; |
107 |
| - return out.str(); |
108 |
| -} |
109 |
| - |
110 |
| -bool _eq(NodePtr l, NodePtr r) |
111 |
| -{ |
112 |
| - while (l && r) { |
113 |
| - if (l->data != r->data) return false; |
114 |
| - l = l->next, r = r->next; |
115 |
| - } |
116 |
| - return (!l && !r); |
117 |
| -} |
118 |
| - |
119 |
| -bool _ne(NodePtr l, NodePtr r) { return !_eq(l, r); } |
120 |
| - |
121 |
| -NodePtr _cp(NodePtr node) |
122 |
| -{ |
123 |
| - NodePtr head = nullptr, tail = nullptr; |
124 |
| - for (int i = 0; node; node = node->next) { |
125 |
| - list_append(tail, node->data); |
126 |
| - if (!i++) head = tail; |
127 |
| - } |
128 |
| - return head; |
129 |
| -} |
130 |
| - |
131 |
| -using ip_t = tuple<NodePtr, int, int>; |
132 |
| - |
133 |
| -void test_impl(vector<ip_t> &ip, vector<NodePtr> &op, shared_ptr<_00_test> f) |
134 |
| -{ |
135 |
| - for (size_t i = 0; i < ip.size(); i++) { |
136 |
| - const string test = format("test-{}", i); |
137 |
| - const auto &[n, s, e] = ip[i]; |
138 |
| - NodePtr t = f->reverseBetween(_cp(n), s, e); |
139 |
| - if (_ne(t, op[i])) { |
140 |
| - cerr << f->getName() << ": " << test << " failed!" |
141 |
| - << " list expected " << _l2s(op[i]) |
142 |
| - << ", actual " << _l2s(t) << "." << endl; |
143 |
| - exit(1); |
144 |
| - } |
145 |
| - |
146 |
| - if (getenv("SHOW_TEST_OUTPUT")) |
147 |
| - cout << " " << test << ": " |
148 |
| - << "input: list = " << _l2s(n) |
149 |
| - << ", start = " << s << ", end = " << e |
150 |
| - << " output: list = " << _l2s(t) << "\n"; |
| 54 | +#define _rev_check(i, m, n, e) \ |
| 55 | + { \ |
| 56 | + NodePtr t = copy(i); \ |
| 57 | + NodePtr a = reverseBetween(t, m, n); \ |
| 58 | + CHECK_EQ(e, a); \ |
| 59 | + SHOW_OUTPUT(i, a); \ |
151 | 60 | }
|
152 |
| -} |
153 | 61 |
|
154 |
| -NodePtr _v2l(const vector<int> v) |
155 |
| -{ |
156 |
| - const int n = static_cast<int>(v.size()); |
157 |
| - NodePtr head = nullptr, tail = nullptr; |
158 |
| - for (int i = 0; i < n; i++) { |
159 |
| - list_append(tail, v[i]); |
160 |
| - if (!i) head = tail; |
| 62 | +#define _rev_desc_prefix "Reverse between" |
| 63 | + |
| 64 | +#define _REV_NAME(var) var |
| 65 | +#define _REV_DESC(var) _rev_desc_prefix " - " _rev_##var##_desc |
| 66 | + |
| 67 | +#define _REV_TEST(var) \ |
| 68 | + TEST(_REV_NAME(var), _REV_DESC(var)) \ |
| 69 | + { \ |
| 70 | + using namespace _REV_NAME(var); \ |
| 71 | + NodePtr ip = copy(vi_t{1, 2, 3, 4, 5}); \ |
| 72 | + vi_t _m{2, 2}; \ |
| 73 | + vi_t _n{4, 2}; \ |
| 74 | + vector<NodePtr> _e{ \ |
| 75 | + copy(vi_t{1, 4, 3, 2, 5}), \ |
| 76 | + copy(vi_t{1, 2, 3, 4, 5}), \ |
| 77 | + }; \ |
| 78 | + int n = size(_e); \ |
| 79 | + for (int i = 0; i < n; i++) \ |
| 80 | + _rev_check(ip, _m[i], _n[i], _e[i]); \ |
161 | 81 | }
|
162 |
| - return head; |
163 |
| -} |
164 |
| - |
165 |
| -void _append_test_data_01(vector<ip_t> &ip, vector<NodePtr> &op) |
166 |
| -{ |
167 |
| - const int s = 2; |
168 |
| - const int e = 4; |
169 |
| - vector<int> t{1, 2, 3, 4, 5}; |
170 |
| - NodePtr i = _v2l(t); |
171 | 82 |
|
172 |
| - t = {1, 4, 3, 2, 5}; |
173 |
| - NodePtr o = _v2l(t); |
| 83 | +_REV_TEST(SinglyLinkedList); |
174 | 84 |
|
175 |
| - ip.emplace_back(i, s, e); |
176 |
| - op.push_back(o); |
177 |
| -} |
178 |
| - |
179 |
| -void _append_test_data_02(vector<ip_t> &ip, vector<NodePtr> &op) |
180 |
| -{ |
181 |
| - const int s = 2; |
182 |
| - const int e = 2; |
183 |
| - vector<int> t{1, 2, 3, 4, 5}; |
184 |
| - NodePtr i = _v2l(t); |
185 |
| - |
186 |
| - t = {1, 2, 3, 4, 5}; |
187 |
| - NodePtr o = _v2l(t); |
188 |
| - |
189 |
| - ip.emplace_back(i, s, e); |
190 |
| - op.push_back(o); |
191 |
| -} |
192 |
| - |
193 |
| -int main(int, char **) |
194 |
| -{ |
195 |
| - vector<ip_t> ip; |
196 |
| - vector<NodePtr> op; |
197 |
| - |
198 |
| - _append_test_data_01(ip, op); |
199 |
| - _append_test_data_02(ip, op); |
200 |
| - |
201 |
| - vector<shared_ptr<_00_test>> impls{ |
202 |
| - make_shared<_01_iterative>(), |
203 |
| - }; |
204 |
| - |
205 |
| - for (size_t i = 0; i < impls.size(); i++) { |
206 |
| - if (getenv("SHOW_TEST_OUTPUT")) |
207 |
| - cout << "Testing implementation " << i + 1 << " " |
208 |
| - << impls[i]->getName() << "\n"; |
209 |
| - |
210 |
| - test_impl(ip, op, impls[i]); |
211 |
| - } |
212 |
| - |
213 |
| - cout << "Executed " << impls.size() << " implementations" |
214 |
| - << " with " << ip.size() << " tests." << endl; |
215 |
| - return 0; |
216 |
| -} |
| 85 | +INIT_TEST_MAIN(); |
0 commit comments