leetcode_234 回文链表
1. 题意
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
2. 题解
2.1 链表转数组
链表不好操作,直接把链表中的数给放进数组里面。
数组里面相向双指针就可以解决了。
/*** 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) {}* };*/
class Solution {
public:bool isPalindrome(ListNode* head) {vector<int> a{};while ( head ) {a.push_back( head->val );head = head->next;}int l = 0;int r = static_cast<int>(a.size()) - 1;while ( l < r) {if ( a[l] != a[r] )return false;l++;r--;}return true;}
};
2.2 栈反转
可以遍历链表一遍把值放入栈中,再依次出栈就是逆序输出了。
/*** 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) {}* };*/
class Solution {
public:bool isPalindrome(ListNode* head) {stack<int> st;auto cur = head;for ( ;cur;cur=cur->next) {st.push(cur->val);}while (head) {if (head->val != st.top())return false;st.pop();head = head->next;}return true;}
};
2.3 尾递归+变量标记
其实这种方法跟栈的做法本质是一样的。
只是变得更加不好理解了。。。
你让我下次写,我不一定能写出来。
/*** 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) {}* };*/
class Solution {
public:bool get_ans(ListNode *head, ListNode * &pre) {if ( head != nullptr ) {bool res = get_ans(head->next, pre);if ( res == false )return false;if ( pre->val != head->val)return false;pre = pre->next;}return true;}bool isPalindrome(ListNode* head) {ListNode *&lp = head;return get_ans( head, lp);}
};
2.4 反转后半部分链表比较
这种做法虽然复杂,但是很有价值。
找到链表的中间位置是leetcode-876. 链表的中间结点。
反转后半部分链表是leetcod-206. 反转链表。
可以先通过快慢指针找到后半部分链表的前驱节点,
进而再找到后半部分链表的头节点。
再比较的时候,我们可以用右半部分遍历完成作为循环条件,
因为这样不需要处理链表节点数为奇数的情况。
前后部分的链不需要断,我们只需要反转一次后半部分进行比较后。
再反转恢复回去就行了。
/*** 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) {}* };*/
class Solution {
public:ListNode *get_mid(ListNode *head) {if (head == nullptr)return nullptr;auto slow = head;auto fast = head->next;while (fast && fast->next) {slow = slow->next;fast = fast->next->next;}return slow;}ListNode *reverse_list(ListNode *head) {ListNode *nHead{};auto cur = head;while ( cur ) { auto nxt = cur->next;cur->next = nHead;nHead = cur;cur = nxt;}return nHead;}// void dump_list(ListNode *head) {// while ( head ) {// cout << head->val << " ";// head = head->next;// }// cout << "\n";// }bool isPalindrome(ListNode* head) {auto pre_r = get_mid( head );auto nHead = reverse_list( pre_r->next );auto lp = head;auto rp = nHead;bool ans{ true };while ( rp ) {if ( lp->val != rp->val ) {ans = false;break;}lp = lp -> next;rp = rp -> next;}reverse_list( nHead );// dump_list( head );return ans;}
};
当然你要非要写左半部分遍历作为条件也不是不可以,
需要额外处理一些东西,包括左右部分链表的断链与恢复,
还有奇数情况的特殊处理,如何判断节点数是奇数呢?
fast
指针值为空。
/*** 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) {}* };*/
class Solution {
public:ListNode * reverseList(ListNode *head) {ListNode *nHead = nullptr;auto cur = head;while ( cur ) {auto nxt = cur->next;cur->next = nHead;nHead = cur;cur = nxt;}return nHead;}void dump_list(const ListNode *head){const ListNode *cur = head;while (cur != nullptr) {cout << cur->val << " ";cur = cur->next;}cout << "\n";}bool isPalindrome(ListNode* head) {if ( head == nullptr || head->next == nullptr )return true;auto slow = head;auto fast = head->next;while ( fast && fast->next ) {slow = slow->next;fast = fast->next->next;}auto lp = head;auto nrHead = reverseList( slow->next );auto rp = nrHead;slow->next = nullptr;auto lend = slow; if ( fast != nullptr )lend = nullptr;bool res{true};while ( lp != lend ) {if ( lp->val != rp->val ) {res = false;break;}lp = lp->next;rp = rp->next;}slow->next = reverseList( nrHead );return res;}
};
3. 参考
leetcode
0x3f