#include #include /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} }; namespace { struct middle_t { ListNode *node; std::size_t size; middle_t(ListNode *node, std::size_t size) : node(node), size(size) {} }; middle_t find_middle(ListNode *head) { ListNode *slow = head; ListNode *fast = head->next; std::size_t size; for (size = 0; fast != nullptr && fast->next != nullptr; size++) { slow = slow->next; fast = fast->next->next; } return {slow, size}; } ListNode *reverse_list(ListNode *tail) { ListNode *previous = nullptr; ListNode *next = nullptr; for (ListNode *current = tail; current != nullptr; previous = current, current = next) { next = current->next; current->next = previous; } return previous; } bool compare_lists(ListNode *left, ListNode *right, std::size_t size) { for (auto i = 0u; i < size + 1; i++) { if (left->val != right->val) { return false; } left = left->next; right = right->next; } return true; } } // namespace class Solution { public: bool isPalindrome(ListNode *head) { // find middle of the linked list auto mid = find_middle(head); // reverse the tail of the linked list auto tail = reverse_list(mid.node); // compare head and tail return compare_lists(head, tail, mid.size); } }; #pragma region Testing utilities namespace { ListNode *construct_list(const std::vector &values) { ListNode *head = new ListNode(values.front()); ListNode *tail = head; for (std::size_t i = 1; i < values.size(); i++) { tail->next = new ListNode(values[i]); tail = tail->next; } return head; } void destroy_list(ListNode *linked_list) { if (linked_list == nullptr) { return; } destroy_list(linked_list->next); delete linked_list; } bool test_find_middle(const std::vector &values, int mid_value) { auto linked_list = construct_list(values); auto mid = find_middle(linked_list); auto result = mid.node->val == mid_value; destroy_list(linked_list); return result; } bool test_isPalindrome(const std::vector &values) { auto linked_list = construct_list(values); Solution s; auto result = s.isPalindrome(linked_list); destroy_list(linked_list); return result; } } // namespace #pragma endregion // Testing utilities int main() { // find_middle tests assert(test_find_middle(std::vector{1, 2, 2, 1}, 2)); assert(test_find_middle(std::vector{1, 2, 3, 2, 1}, 3)); assert(test_find_middle(std::vector{1, 2}, 1)); assert(test_find_middle(std::vector{1}, 1)); // isPalindrome tests assert(test_isPalindrome(std::vector{1, 2, 2, 1})); assert(test_isPalindrome(std::vector{1, 2, 3, 2, 1})); assert(!test_isPalindrome(std::vector{1, 2})); assert(test_isPalindrome(std::vector{1})); return 0; }