思路:
想法1:快慢指针遍历一遍字符串得到字符串长度以及中间结点的位置,然后对后半部分链表反转,最后从头比较前半部分链表和反转后的后半部分链表;
想法2:利用栈先进后出和函数参数引用来对字符串进行递归比较!
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
void check(ListNode *head1, int l, ListNode *&head2, int r, bool &flag) //判断链表[l~r]是否为回文 (注意head2是变化的 它要一次次往后走 一定要引用)
{
if (l >= r)
{
return;
}
if (r - l >= 2)
{
check(head1->next, l + 1, head2, r - 1, flag);
}
int a = head1->val, b = head2->val;
if (a != b)
{
flag = false;
}
//head2指向下一个结点,此时该函数完成返回其调用函数时,head1也指向前一个结点,这样又能比较两个数是否相等了
head2 = head2->next;
}
bool isPalindrome(ListNode *head)
{
//如果有1个及以下的元素,返回true
if (head == nullptr || head->next == nullptr)
{
return true;
}
//利用快慢指针求链表个数和中间节点
int size = 0;
ListNode *slow = head, *fast = head, *mid_point = nullptr;
while (fast)
{ //find mid node
size++;
slow = slow->next;
fast = fast->next ? fast->next->next : fast->next;
}
mid_point = slow;
while (slow)
{
size++;
slow = slow->next;
}
bool flag = true;
check(head, 1, mid_point, size, flag);
return flag;
}
//之前的思路: 其一,find mid node 使用快慢指针找到链表中点。 其二,reverse 逆序后半部分。 其三,check 从头、中点,开始比较是否相同。
// bool isPalindrome(ListNode* head) {//O(n)、O(1)
// ListNode* slow = head, *fast = head, *prev = nullptr;
// while (fast){//find mid node
// slow = slow->next;
// fast = fast->next ? fast->next->next: fast->next;
// }
// while (slow){//reverse
// ListNode* temp = slow->next;
// slow->next = prev;
// prev = slow;
// slow = temp;
// }
// while (head && prev){//check
// if (head->val != prev->val){
// return false;
// }
// head = head->next;
// prev = prev->next;
// }
// return true;
// }
int main()
{
ListNode *a1 = new ListNode(1);
ListNode *a2 = new ListNode(2);
ListNode *a3 = new ListNode(2);
ListNode *a4 = new ListNode(1);
a1->next = a2;
a2->next = a3;
a3->next = a4;
cout << isPalindrome(a1);
return 0;
}