问题描述:
给定一单链表头结点,判断该链表是否具有回文结构.
/*
* 回文结构的判断
* Input 1 -> 2 -> 3 -> 2 -> 1 return true
* Input 1 -> 2 -> 3 -> 4 -> 1 return false
*/
算法一:
借助一个堆栈(利用堆栈的先进后出特性),遍历链表依次压栈,再次遍历链表、遍历的过程中依次弹出堆栈的元素进行比较,若均相等则该链表具有回文结构。
代码实现如下:
/*
* 借助一堆栈实现
*/
public static boolean selution(Node<Integer> head) {
boolean result = true;
Stack<Node<Integer>> stack = new Stack<>();
Node<Integer> point = head;
while (point != null) {
stack.push(point);
point = point.next;
}
point = head;
while (point != null) {
if(stack.pop().data != point.data) {
result = false;
break;
}
point = point.next;
}
return result;
}
上述算法时间复杂度为O(N),由于需要使用一个跟链表长度相同大小的堆栈,其空间复杂度亦为O(N)。
算法二:
/*
* 1.找到中间元素 1 -> 2 -> 3 -> 2 -> 1 找到3
* 2.将右边元素逆序 1 -> 2 -> 3 <- 2 <- 1
* 3.分别从两头开始遍历,进行判断
* 4.判断完成后恢复现场 1 -> 2 -> 3 -> 2 -> 1
*/
实现代码如下:
public static boolean selution2(Node<Integer> head) {
boolean result = true;
//1. 找到中间元素
Node<Integer> pointSlow = head;
Node<Integer> pointFast = head;
while(pointFast.next != null && pointFast.next.next != null) {
pointSlow = pointSlow.next;
pointFast = pointFast.next.next;
}
// 2.右边元素逆序
Node<Integer> rightHead = pointSlow.next;//后半段
pointSlow.next = null;
rightHead = ReverseList.reverseList(rightHead);
// 3.左右指针依次移动比较
for(Node<Integer> pLeft = head, pRight = rightHead; pRight != null;
pRight = pRight.next, pLeft = pLeft.next) {
if(pLeft.data != pRight.data) {
result = false;
break;
}
}
// 4.恢复现场
rightHead = ReverseList.reverseList(rightHead);
Node<Integer> leftLast = head;
while(leftLast.next != null) {
leftLast = leftLast.next;
}
leftLast.next = rightHead;
return result;
}
public class ReverseList {
public static Node<Integer> reverseList(Node<Integer> head){
if(head.next == null) {//长度为1
return head;
}
//init
Node<Integer> pFir = head;
Node<Integer> pSec = head.next;
Node<Integer> pTemp = head.next;
head.next = null;//尾结点指空
//
while(pTemp != null) {
pTemp = pTemp.next;
pSec.next = pFir;//后一个指针指向前一个元素
pFir = pSec;//更新前指针
pSec = pTemp;//更新后指针
}
head = pFir;
return head;
}
}
上述算法的时间复杂度为O(N),空间复杂度为O(1);