判断链表是否是回文结构
题目: 给定一个链表的头节点head,请判断链表是否是回文结构。
例子:1-2-1 返回true,12-3-12 返回true, 1-2-3 返回false.
使用堆栈的方式来判断是否是回文结构。
思路,将链表的节点压进栈中,利用栈的先进后出的特点,不断弹出和链表中的节点进行对比,来判断是否是回文结构。
先定义一个链表结构。
public static class Node{
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
上代码:
public static boolean isPalindrome(Node head){
//单节点和null 认为是回文结构。
if (head == null || head.next == null){
return true;
}
//将节点压进栈中
Node cur = head;
Stack<Node> nodes = new Stack<>();
while (cur != null){
nodes.add(cur);
cur = cur.next;
}
cur = head;
//弹出节点去判断。
while (!nodes.isEmpty()){
if (nodes.pop().val != cur.val){
return false;
}
cur = cur.next;
}
return true;
}
快慢指针加栈来实现
通过快慢指针,先找出链表的中间节点,把中间节点后面的节点压进栈中,然后只比对一半的节点就可以实现判断。
代码演示:
public static boolean isPalindrome2(Node head){
if (head == null || head.next == null){
return true;
}
//奇数长度找到中间节点,偶数节点找到链表的下中点。
Node right = head.next;
Node fast = head;
while (fast.next != null && fast.next.next != null){
right = right.next;
fast = fast.next.next;
}
//压进栈中
Stack<Node> nodes = new Stack<>();
while (right != null){
nodes.add(right);
right = right.next;
}
Node cur = head;
while (!nodes.isEmpty()){
if (nodes.pop().val != cur.val){
return false;
}
cur = cur.next;
}
return true;
}
解法三: 取出后半段数字进行翻转。
将后半段的节点逆序,演示:1->2->3->3->2->1, 后半段逆序成:
1->2->3<-3<-2<-1 ,然后拿到头节点和尾节点,循环进行判断,判断完成后,再将链表顺序调整回去。
代码演示
public static boolean isPalindrome6(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.val != n2.val) {
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;
}
不熟悉快慢指针。可以查看上篇文章。
快慢指针法来确定链表中间位置