#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; }