回文链表判断

回文字符串和数组我们会经常遇到,今天讲一个相关问题,叫回文链表,还是和以前一样,先把代码提上来。

	// need O(1) extra space
	public static boolean isPalindrome3(Node head) {
		if (head == null || head.next == null) {
			return true;
		}
		Node n1 = head;
		Node n2 = head;
		while (n2.next != null && n2.next.next != null) { // find mid node
			n1 = n1.next; // n1 -> mid
			n2 = n2.next.next; // n2 -> end
		}
		// n1 中点
		
		
		n2 = n1.next; // n2 -> right part first node
		n1.next = null; // mid.next -> null
		Node n3 = null;
		while (n2 != null) { // right part convert
			n3 = n2.next; // n3 -> save next node
			n2.next = n1; // next of right node convert
			n1 = n2; // n1 move
			n2 = n3; // n2 move
		}
		n3 = n1; // n3 -> save last node
		n2 = head;// n2 -> left first node
		boolean res = true;
		while (n1 != null && n2 != null) { // check palindrome
			if (n1.value != n2.value) {
				res = false;
				break;
			}
			n1 = n1.next; // left to mid
			n2 = n2.next; // right to mid
		}
		n1 = n3.next;
		n3.next = null;
		while (n1 != null) { // recover list
			n2 = n1.next;
			n1.next = n3;
			n3 = n1;
			n1 = n2;
		}
		return res;
	}

这段代码比传统方式要快很多,下面讲一下具体的流程:

  1. if (head == null || head.next == null):首先检查链表是否为空或只包含一个节点,因为这种情况下链表必然是回文,所以直接返回 true

  2. 初始化两个指针 n1n2 都指向链表的头节点 head。这两个指针将用于查找链表的中间节点。

  3. 进入一个循环,条件是 n2.next != null && n2.next.next != null,循环中 n1 每次移动一步,而 n2 每次移动两步,这样当 n2 到达链表尾部时,n1 恰好指向链表的中间节点(如果链表长度为奇数,则中间节点只有一个;如果链表长度为偶数,则中间节点有两个,这里 n1 指向靠左的那一个)。

  4. n2 移动到 n1 的下一个节点,这是为了将链表分为两部分:左边部分和右边部分。

  5. 断开 n1n2 之间的连接,即将 n1.next 设置为 null,从而分割链表为两个独立的部分。

  6. 接下来是将右边部分(后半部分)的链表反转。使用三个指针 n1n2n3 分别指向当前节点、下一个节点和用于保存下下一个节点。通过循环,不断将当前节点的 next 指针反向指向前一个节点,完成链表的反转。

  7. 在反转完成后,n3 会指向反转后链表的头节点,而 n2 则指向左边部分链表的头节点。同时, n1 指向 n3,表示将 n1 移动到反转链表的头节点位置。

  8. 接下来,使用两个指针 n1n2 同时遍历左边部分和反转后的右边部分,比较它们的值是否相等。如果有任何不相等的情况出现,将 res 设置为 false,表示链表不是回文。

  9. 最后,需要将右边部分的链表再次反转回来,以恢复原始链表的结构。这是通过循环和指针操作实现的。

  10. 返回 res,表示是否判断链表为回文。

 

假设输入链表为:1 -> 2 -> 3 -> 2 -> 1

  1. 首先找到链表的中间节点,n1 指向节点 3。

  2. 将右边部分反转,得到链表:1 -> 2 -> 3 和 1 -> 2。

  3. 通过比较左右两边部分的值,发现它们是回文的。

  4. 最后将右边部分反转回来,得到原始链表:1 -> 2 -> 3 -> 2 -> 1。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ITIRONMAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值