234.Palindrome Linked List
给定一个单链表,求其是否可回读,即,正着读和倒着读一样。
Input: 1->2->2->1
Output: true
思路:
一、遍历链表,将其节点的值存入动态数组中,最后对数组头尾的值遍历判别。
bool isPalindrome(ListNode* head) { vector<int> tmp; while (head) { tmp.push_back(head->val); head = head->next; } int i = tmp.size(); for (int j = 0; j < i/2; j++) { if (tmp[j] != tmp[i - j - 1]) return false; } return true; }
二、利用快慢指针,fast指针每次走2步,slow指针每次走一步,当fast走到结尾的时候,slow刚好走到链表的中点。利用栈,将slow走的节点的值存起来,当slow走到链表中点后,每走一步就将节点的值和栈的值比较。注意判断链表节点个数为奇数或偶数时,处理稍有差别。
bool isPalindrome(ListNode* head) { ListNode* fast = head; ListNode* slow = head; stack<int> s; while (fast && fast->next) { s.push(slow->val); fast = fast->next->next; slow = slow->next; } if (fast) slow = slow->next; //如果链表节点个数为奇数 while (slow) { if (slow->val != s.top()) return false; s.pop(); slow = slow->next; } return true; }
Java 版:
• 先得到链表的长度 n,将链表的后一半,翻转;
• 比较前一半与翻转后的另一半链表;
• 对于 n 为奇数的情况,其实不影响,比如: n = 5,则后面翻转的节点个数为 2 个;
• 比较前面 2 个与后面 2个,而中间的一个节点,不用比较,忽略即可。
class Solution { public boolean isPalindrome(ListNode head) { int n = 0; ListNode tmpHead = head; while(tmpHead != null){ n++; //统计链表的节点个数 tmpHead = tmpHead.next; } tmpHead = head; n = n / 2; while(n-- > 0) tmpHead = tmpHead.next; ListNode reverse = reverseList(tmpHead); //反转 while(reverse != null){ //比较反转后的链表,与正序链表 if(head.val != reverse.val) return false; head = head.next; reverse = reverse.next; } return true; } private ListNode reverseList(ListNode head){ //反转链表 ListNode res = null, tmp = null; while(head != null){ tmp = head.next; head.next = res; res = head; head = tmp; } return res; } }