题目:请判断一个链表是否为回文链表。
注意:单个节点,或者null也算回文链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
//思路1:双指针法,本意可以从链表的开头和结尾分别进行对比,但是链表是单向的,不能往前遍历,所以考虑将链表放入到数组中进行前后比较
class Solution {
//[1,0,1]属于回文链表
//首先这个题,和“有效的括号”的那道题有点像,所以可以一起总结,这道题用栈比较好,遍历链表,先进后出,但是要看长度是奇偶数,如果是奇数,则放如一半,然后跳过中间的数,如果是偶数,放入一半,然后前一半和后一半进行对比
public boolean isPalindrome(ListNode head) {
ArrayList<Integer> array = new ArrayList<Integer>();
while(head!=null){
array.add(head.val);
head=head.next;
}
//放如到了数组中
int front = 0;
int back = array.size()-1;
//进行比较
while(front<=back){
if(array.get(front)!=array.get(back)){
return false;
}
front++;
back--;
}
return true;
}
}
// 思路2:我们考虑找到回文链表,将链表分成前后两个部分,然后将后面的链表反转,然后再和后半截链表的头节点以及前半链表的头节点进行比较
// Ⅰ、如何确定后半部分的头节点?因为对于回文链表,是链表个数一分为二,我们可以想象成龟兔赛跑,乌龟和兔子分别每次走一步,和两步,当兔子
// 走到最后的时候,那么乌龟就到了前半链表的尾部
// Ⅱ、找到前半链表的尾部,我们可以对后面的链表进行反转
// Ⅲ、然后我们用链表的前半截链表的头节点与后半截反转后的链表的头节点依次比较
class Solution {
public boolean isPalindrome(ListNode head) {
//先判断是否为空链表
if(head==null){
return true;
}
//第Ⅲ步,我们用链表的前半截链表的头节点与后半截反转后的链表的头节点依次比较
//首先我们按第一步求出前半截链表的尾部
ListNode firstOFHalfEnd = endOfFirstHarf(head);
//其次我们按第二步反转后半部分的链表
ListNode secondOfHarfStart = reverseList(firstOFHalfEnd.next);
//最后我们开始比较
ListNode p1 = head;
ListNode p2 = secondOfHarfStart;
//按第三步进行比较
while(p2!=null){
if(p1.val!=p2.val){
return false;
}
p1 = p1.next;
p2 = p2.next;
}
return true;
}
//第Ⅰ步 返回的前半截链表的尾部
public ListNode endOfFirstHarf(ListNode head){
ListNode slow = head;
ListNode fast = head;
while(fast.next!=null&&fast.next.next!=null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
//第Ⅱ步 反转后半截链表的头节点
public ListNode reverseList(ListNode head){
ListNode pre = null;
ListNode cur = head;
ListNode temp;
while(cur!=null){
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
//思路3:递归思想:最巧的思想,将开头和结尾进行比较,正好符合递归思想,但是要注意递归的思想用的是栈,所以空间复杂度是O(n)
class Solution {
//设置一个变量,为了去结尾的变量进行比较
private ListNode preNode;
//构造一个递归函数
public boolean recursiveFun(ListNode curNode){
if(curNode!=null){
//递归头,如果传回的是false
if(!recursiveFun(curNode.next)){
return false;
}
//递归体
if(curNode.val!=preNode.val){
return false;
}
preNode = preNode.next;
}
return true;
}
public boolean isPalindrome(ListNode head) {
preNode = head;
return recursiveFun(head);
}
}