什么是回文链表?
就是下面这种:
[1,2,2,1] 倒过来仍然是[1,2,2,1],啊,“上山西去运煤,煤运去西山上” 就是这个感觉。
第一种方法:
/*
* 步骤1:找中间节点
* 步骤2:将中间节点后半段反转
* 步骤3:比较两段
* */
步骤1:找中间节点
使用快慢指针法找中间节点,让p1一次走一步,p2一次走两步,等p2走完了,p1刚好走了一半,这样就找到中间节点了。
/**
* 找中间节点
* @param head 原链表的头结点
* @return 中间节点
*/
private ListNode mid(final ListNode head)
{
ListNode p1 = head;
ListNode p2 = head;
while (p2 != null && p2.getNext() != null)
{
p1 = p1.getNext();
p2 = p2.getNext().getNext();
}
return p1;
}
步骤2:将中间节点后半段反转
反转链表我前面有几篇博客已经专门介绍了,这里就不过多解释了。
/**
* 反转链表
* @param oldHead 原链表的头结点
* @return 反转后的链表的头结点
*/
private ListNode reverse(ListNode oldHead)
{
ListNode newNode = null;
while (oldHead != null)
{
ListNode oldNode = oldHead.getNext();
oldHead.setNext(newNode);
newNode = oldHead;
oldHead = oldNode;
}
return newNode;
}
步骤3:比较两段
/**
* 判断回文链表
* @param oldHead 原链表的头结点
* @return 是否是回文链表
*/
public boolean isPalindrome(ListNode oldHead)
{
ListNode newHead = reverse(mid(oldHead));//通过前两步得到一个反转了的后半段链表
while (newHead != null)//只要得到的新链表不为空就一直比较下去
{
if (newHead.getVal() == oldHead.getVal())//两个链表的值相等,继续往后面比较
{
newHead = newHead.getNext();
oldHead = oldHead.getNext();
}
else//一旦有不相等,直接返回false
{
return false;
}
}
return true;
}
第二种方式:
第二种是对第一种的优化:
/* 优化
* 步骤1:找中间节点的同时将前半段反转
* 步骤2:比较前半段的反转与后半段
* */
由于第一种方式走了三次循环,所以它的时间复杂度不理想,现在采用 ’找中间节点的同时将前半段反转‘ 的方式来减少一个循环
/**
* 判断回文链表
* @param oldHead 原链表的头结点
* @return 是否是回文链表
*/
public boolean isPalindrome2(ListNode oldHead)
{
ListNode[] listNodes = mid2(oldHead);
ListNode reverseList = listNodes[1];
ListNode mid = listNodes[0];
while (mid != null)
{
if (mid.getVal() == reverseList.getVal())
{
mid = mid.getNext();
reverseList = reverseList.getNext();
}
else
{
return false;
}
}
return true;
}
/**
* 找中间节点
* @param head 原链表的头结点
* @return 中间节点和前半段反转后的链表的头结点
*/
private ListNode[] mid2(ListNode head)
{
ListNode p1 = head;
ListNode p2 = head;
ListNode oldHead = head;
ListNode newHead = null;
while (p2 != null && p2.getNext() != null)
{
//找中间节点
p1 = p1.getNext();
p2 = p2.getNext().getNext();
//反转前半段
oldHead.setNext(newHead);
newHead = oldHead;
oldHead = p1;
}
if (p2 != null)//如果链表长度为奇数,就把中间节点后移
{
p1 = p1.getNext();
}
return new ListNode[]{p1, newHead};
}