回文链表判断

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

	// 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。

你可能感兴趣的:(链表,数据结构)