zoukankan      html  css  js  c++  java
  • LeetCode234.回文链表

    题目

    给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

    示例 1:
    

    输入:head = [1,2,2,1]
    输出:true
    
    示例 2:
    

    输入:head = [1,2]
    输出:false
    
    
    提示:
    
    链表中节点数目在范围[1, 105] 内
    0 <= Node.val <= 9
    

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/palindrome-linked-list
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    解题方法

    将值复制到数组中后用双指针

    1.复制链表的值到数组中
    2.使用双指针判断是否为回文
    
    时间复杂度:O(n)空间复杂度:O(n)
    

    递归

     时间复杂度:O(n)空间复杂度:O(n)
    

    快慢指针

    1.找到前半部分链表的位节点
    2.反转后半部分链表
    3.判断是否回文
    4.恢复链表
    5.返回结果
    
    时间复杂度:O(n)空间复杂度:O(1)
    

    代码

    type ListNode struct {
    	Val int
    	Next *ListNode
    }
    
    // 数组+双指针
    func isPalindrome(head *ListNode) bool {
    	vals := []int{}
    	// 遍历一遍节点值添加到数组
    	for ;head != nil;head  = head.Next{
    		vals = append(vals,head.Val)
    	}
    	n := len(vals)
    	// 双指针从头和尾比较
    	for i,v := range vals[:n/2]{
    		if v != vals[n-1-i]{
    			return false
    		}
    	}
    	return true
    }
    
    // 递归
    func isPalindrome2(head *ListNode) bool {
    	frontPointer := head
    	var recursivelyCheck func(node *ListNode) bool
    	recursivelyCheck = func(node *ListNode) bool {
    		if node != nil{
    			if !recursivelyCheck(node.Next){
    				return false
    			}
    			if node.Val != frontPointer.Val{
    				return false
    			}
    			frontPointer = frontPointer.Next
    		}
    		return true
    	}
    	return recursivelyCheck(head)
    }
    
    
    // 反转链表
    func reversList(head *ListNode) *ListNode {
    	var prev,cur *ListNode = nil,head
    	for cur != nil{
    		nextTmp := cur.Next
    		cur.Next = prev
    		prev = cur
    		cur = nextTmp
    	}
    	return prev
    }
    
    // 快慢指针找到前半部分链表尾节点
    func endOfFirstHalf(head *ListNode) *ListNode {
    	fast,slow := head,head
    	// 快指针速度为慢指针两倍,快指针走到尽头,慢指针走一半
    	for fast.Next != nil && fast.Next.Next != nil{
    		fast = fast.Next.Next
    		slow = slow.Next
    	}
    	return slow
    }
    
    // 快慢指针
    func isPalindrome3(head *ListNode) bool {
    	if head == nil{
    		return true
    	}
    	// 获取前半部分链表尾节点
    	firstHalfEnd := endOfFirstHalf(head)
    	// 反转后半部分节点
    	secondHalfStart := reversList(firstHalfEnd.Next)
    
    	// 与反转后的后半部分链表比较判断是否是回文
    	p1,p2 := head,secondHalfStart
    	result := true
    	for result && p2 != nil{
    		if p1.Val != p2.Val{
    			result = false
    		}
    		p1 = p1.Next
    		p2 = p2.Next
    	}
    	// 还原链表反转
    	firstHalfEnd.Next = reversList(secondHalfStart)
    	return result
    }
  • 相关阅读:
    [转载]NSDistributedNotificationCenter
    protobuf在IOS中的使用
    mac 下大dmg文件分割成多部分
    IOS 后台任务、多任务的理解2
    越狱iPhone、ipad通过网页安装ipa
    Android中的几种多线程实现
    Android多线程-AsyncTask异步任务
    2----IOS、Android数据存储方式
    Andriod 页面跳转传值
    svn 分支创建 合并
  • 原文地址:https://www.cnblogs.com/hzpeng/p/15233677.html
Copyright © 2011-2022 走看看