请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
- 找到链表中点
- 反转中点后半段
- 两个指针,一个从前往后,一个从后往前,匹配比较,直到两指针相遇。
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func isPalindrome(head *ListNode) bool {
//空链表是特殊的回文链表
if(head==nil){
return true
}
//重新反转后的链表后半段
reList:=ReverseList(midNode(head))
//result的初始值为前半段第一节点和反转后的后半段第一节点比较
result:=head.Val==reList.Val
//双方遍历,直至指针相遇
for reList!=head&&reList!=nil&&head!=nil{
//依次相与,若有一个false则全false
result=result&&head.Val==reList.Val
//更新两个指针
reList=reList.Next
head=head.Next
}
return result
}
//找到链表的中间节点并返回
func midNode(head *ListNode) *ListNode{
//快慢指针
slowp,fastp:=head,head
for fastp!=nil&&fastp.Next!=nil{
//快指针速度是慢指针2倍
slowp=slowp.Next
fastp=fastp.Next.Next
}
//当快指针到达链表尾部的时候慢指针所指位置就是链表的中间节点
return slowp
}
//传入链表中间节点,反转后半部分
func ReverseList(head *ListNode) *ListNode{
if head==nil{
return head
}
var pre,next *ListNode//定义前驱节点和后继节点
for head!=nil{//如果没到链表尾部
next=head.Next//暂存后继节点
head.Next=pre//当前节点指针域指向前驱节点
pre=head//后移准备改变下一个节点
head=next//后移
}
return pre
}