如何判断一个单链表是回文单链表?
- LeetCode题目链接
- 下面是LeetCode的题目截图:
思路分析
回文单链表:链表反转后和原链表一样
- 思路一:根据回文单链表的特点很容易分析出
① 反转单链表
② 遍历比较原链表和反转后的链表,如果有不一样的结点,说明不是回文的,如果两链表完全一样,说明是回文的 - 思路二:
① 使用快慢指针找出链表的中间结点,其中快指针步长为2,慢指针步长为1
② 根据中间结点反转后半部分链表
③ 遍历比较前后两部分链表的结点是否一致
反转实现
由于两个思路都需要反转,这里先实现一下单链表反转
-
图示
-
代码实现
public static ListNode reverseLinked(ListNode head) {
if(head == null) {
return head;
}
// 当前结点
ListNode cur = head;
// 反转后的链表
ListNode newHead = new ListNode(head.val);
// 遍历原链表,构造反转链表
while (true) {
if (cur.next == null) {
newHead.val = cur.val;
break;
}
ListNode nextTemp = newHead.next;
newHead.next = new ListNode(cur.val);
newHead.next.next = nextTemp;
// 结点后移,继续遍历
cur = cur.next;
}
return newHead;
}
思路一实现
public boolean isPalindrome(ListNode head) {
// 反转链表
ListNode reservedListNode = reverseLinked(head);
// 遍历比较原链表和反转后链表的结点
ListNode cur = head;
ListNode cur1 = reservedListNode;
while (cur != null && cur1 != null) {
if (cur.val != cur1.val) {
return false;
}
// 后移,继续遍历比较
cur = cur.next;
cur1 = cur1.next;
}
return true;
}
思路二实现
-
图示
结点个数为奇数:当满足fast.next = null时,slow指向中间结点
结点个数为偶数:当满足fast.next.next = null时,slow指向中间结点 -
代码实现
public boolean isPalindrome2(ListNode head) {
// 使用快慢指针找出中间结点
ListNode middle = getMiddle(head);
// 反转后半部分链表
ListNode reverseLinked = reverseLinked(middle);
// 比较前后两部分链表
ListNode cur = head;
ListNode cur1 = reverseLinked;
while (cur != null && cur1 != null) {
if (cur.val != cur1.val) {
return false;
}
// 后移
cur = cur.next;
cur1 = cur1.next;
}
return true;
}
private static ListNode getMiddle(ListNode head) {
if(head == null) {
return head;
}
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// 不管链表结点个数是奇数还是偶数,循环退出,slow就是中间结点
return slow;
}