原题
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
题目分析
根据回文数定义和单链表特点,求单链表是否为回文链表。要求时间复杂度O(n),空间复杂度O(1)。
思路,将后半部分反转,与前半部分元素一一比较。
代码实现
主题框架:
public bool IsPalindrome(ListNode head)
{
int nodeCnt = nodeCount(head);
ListNode begNode = head;
//反转后半部分
ListNode midNode = head;
int i = 0;
int mid = nodeCnt % 2 == 0 ? nodeCnt / 2 : nodeCnt / 2 + 1;
while (++i <= mid)
midNode = midNode.next;
i = 0;
ListNode rmidNode = ReverseList(midNode);
//后半部分反转后,如果是回文,则前半、后半对应元素相等
while (i++ < nodeCnt/2)
{
if (begNode.val != rmidNode.val)
return false;
begNode = begNode.next;
rmidNode = rmidNode.next;
}
return true;
}
判断单链表节点个数:
private int nodeCount(ListNode head)
{
int cnt = 0;
while (head != null)
{
cnt++;
head = head.next;
}
return cnt;
}
反转链表,参数为待反转链表的头部。
public ListNode ReverseList(ListNode head)
{
if (head == null || head.next == null)
return head;
ListNode a = head;
ListNode b = head.next;
a.next = null;
while (b != null)
{
ListNode tmp = b.next; //保存节点b后的所有节点顺序
b.next = a; //上步保存后,可以放心的将b的next域指向a,实现反转
a = b; //上步实现反转后,再赋值给a,这样a始终为反转链表的头节点
b = tmp;//上步后实现了反转,这步实现迭代,即让b再在原来的链表中保持前行。
}
return a;
}