当前位置 博文首页 > tzh_linux的专栏:leetcode 234. 回文链表 golang实现

    tzh_linux的专栏:leetcode 234. 回文链表 golang实现

    作者:[db:作者] 时间:2021-08-14 21:07

    描述
    请判断一个链表是否为回文链表。
    
    示例 1:
    
    输入: 1->2
    输出: false
    示例 2:
    
    输入: 1->2->2->1
    输出: true
    进阶:
    你能否用O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
    
    思路
    1. 利用快慢指针 找到链表的中间节点
    2. 满指针在遍历的时候将前半部分的链表反转
    3. p1 p2 分别指向中间节点开始遍历判断是否相等
    
    1 -> 2 -> 2 -> 1  反转后 1 <- 2  2-> 1 p1=2 p2=2
    1 -> 2 -> 0 -> 2 -> 1 反转后 1 <- 2  0->2->1  p1=2 p2 = 2
    
    实现
    /**
     * Definition for singly-linked list.
     * type ListNode struct {
     *     Val int
     *     Next *ListNode
     * }
     */
    func isPalindrome(head *ListNode) bool {
    	if head == nil || head.Next == nil{
    		return true
    	}
    
    	slow := head
    	fast := head.Next // 这里必须是从fast=head.Next 开始 
    	var pre *ListNode
    	var prepre *ListNode
    
    	for fast != nil && fast.Next != nil{
    		prepre = pre
    		pre = slow
    
    		slow = slow.Next
    		fast = fast.Next.Next
    
    		pre.Next = prepre
    	}
    	
    	//  slow即为中间节点 此时 pre 和pre之间都已反转 slow还没有指向pre 因为我们还需要通过slow找到后面的节点
    
    	var p1 *ListNode
    	var p2 *ListNode
    	// 这里根据fast == nil 还是fast.Next == nil 可以判断链表节点是奇数还是偶数
    	if fast == nil{     // 奇数
    		p2 = slow.Next  // 奇数个 则p2 为中间节点的Next
    		p1 = pre        // p1 为中间节点的上一个
    		
    	}else{              // fast.Next == nil 偶数个
    		p2 = slow.Next  // p2 为中间节点slow的下一个
    		p1 = slow       // p1 为slow
    		slow.Next = pre // 将slow节点指向slow的上一个节点
    	}
    
    	for p1 != nil{
    		if p1.Val != p2.Val{
    			return false
    		}
    
    		p1 = p1.Next
    		p2 = p2.Next
    	}
    
    	return true
    }
    
    cs