【图解链表类面试题】如何判断一个单链表是否是回文链表?(两种实现)

目录

题目描述

利用数组

双指针+反转


题目描述

题目地址:https://leetcode-cn.com/problems/palindrome-linked-list/

请判断一个链表是否为回文链表。
示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

利用数组

首先我们来解释下,什么叫回文。把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。因为正反都一样,意味着以一个中间节点为基准,一个指针从开头往中间走,另一指针走结尾往中间走,两个指针不断遍历比较的结果应该是一样的。
比如下面这个字符串:

1234321

上图中的中间点是4,所以分割完后,再将后半部分颠倒

123
123

所以这个字符串就是回文串。
对于链表我们可以这么做:
将所有元素放到一个数组中,再利用双指针迭代比较元素中的内容

【图解链表类面试题】如何判断一个单链表是否是回文链表?(两种实现)_第1张图片

两个指针不断往中间迭代比较

【图解链表类面试题】如何判断一个单链表是否是回文链表?(两种实现)_第2张图片

 

java实现:

class Solution {
	public boolean isPalindrome(ListNode head) {
		if(head==null || head.next==null) {
			return true;
		}
		java.util.ArrayList arr = new java.util.ArrayList();
		//申请一个容器,然后把元素都放到数组中
		while(head!=null) {
			arr.add(head.val);
			head = head.next;
		}
		int i = 0;
		int j = arr.size()-1;
		//用i和j两个指针,一个往后,一个往前,不断迭代
		//如果i的值不等于j说明不是回文,反之是回文
		while(i

python实现:

class Solution(object):
	def isPalindrome(self, head):
		"""
		:type head: ListNode
		:rtype: bool
		"""		
		if not (head and head.next):
			return True
		arr,i = [],0
		# 申请一个数组,然后把元素都放到数组中
		while head:
			_,head = arr.append(head.val),head.next
		j = len(arr)-1
		# 用i和j两个指针,一个往后,一个往前,不断迭代
		# 如果i的值不等于j说明不是回文,反之是回文
		while i

双指针+反转

我们利用链表的两个操作:

  1. 找到链表的中间节点

  2. 反转链表

通过这两个操作之后,原链表就以中间节点被一分为二
前半部分一个链表,后半部分(被反转了)为一个链表
然后遍历这两个链表,如果遍历过程中发现两个链表节点不同,就说不是回文链表,直接返回false即可
如果链表遍历完了,说明是回文链表
注意一个小细节,如果链表长度是偶数的话,前半部分和后半部分长度是一样的
如果链表长度是奇数,那么前半部分的长度比后半部分长度多1个
所以最后迭代链表的时候,以后半部分为准就可以了,当链表总长为奇数时,前半部分的最后一个节点就不会被遍历到了。

【图解链表类面试题】如何判断一个单链表是否是回文链表?(两种实现)_第3张图片

 

动态如如下:

【图解链表类面试题】如何判断一个单链表是否是回文链表?(两种实现)_第4张图片

 

java实现:

class Solution {
	public boolean isPalindrome(ListNode head) {
		//边界条件不用忘记了
		if(head==null || head.next==null) {
			return true;
		}
		ListNode p = new ListNode(-1);
		ListNode low = p;
		ListNode fast = p;
		p.next = head;
		//快慢指针不断迭代,找到中间节点
		while(fast!=null && fast.next!=null) {
			low = low.next;
			fast = fast.next.next;
		}
		ListNode cur = low.next;
		ListNode pre = null;
		low.next = null;
		low = p.next;
		//将链表一分为二之后,反转链表后半部分
		while(cur!=null) {
			ListNode tmp = cur.next;
			cur.next = pre;
			pre = cur;
			cur = tmp;
		}
		//将链表前半部分和 反转的后半部分对比
		while(pre!=null) {
			if(low.val!=pre.val) {
				return false;
			}
			low = low.next;
			pre = pre.next;
		}
		return true;
	}
}

python实现

class Solution(object):
	def isPalindrome(self, head):
		"""
		:type head: ListNode
		:rtype: bool
		"""
		# 边界条件不用忘记了
		if not (head and head.next):
			return True
		p = ListNode(-1)
		p.next,low,fast = head,p,p
		# 快慢指针不断迭代,找到中间节点
		while fast and fast.next:
			low,fast = low.next, fast.next.next
		cur,pre = low.next,None
		low.next = None
		#将链表一分为二之后,反转链表后半部分
		while cur:
			cur.next,pre,cur = pre,cur,cur.next
		a,b = p.next,pre
		# 将链表前半部分和 反转的后半部分对比
		while b:
			if a.val!=b.val:
				return False
			a,b = a.next,b.next
		return True

欢迎扫描关注公众号 有更多图解的算法面试题等你哦~

【图解链表类面试题】如何判断一个单链表是否是回文链表?(两种实现)_第5张图片

你可能感兴趣的:(算法题,链表,算法,leetcode,面试)