一、O(n)时间复杂度和O(1)空间复杂度判断单链表是否是回文链表
算法题描述:
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
输入:head = [1,2,2,1]
输出:true
输入:head = [1,2]
输出:false
二、代码实例
代码如下(示例):
/**
* 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; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
//逆置后半段 然后从头开始遍历
//现找出链表长度
int length = 0;
ListNode l1 = head;
while(l1 != null){
length ++;
l1 = l1.next;
}
//找到中间位置,长度为奇数和长度为偶数 中间位置不一样
int k = 1;
ListNode mid = head;
if(length % 2 == 0){
while(k < length/2){
k++;
mid = mid.next;
}
}else{
while(k <= length/2){
k++;
mid = mid.next;
}
}
//用头插法将后半段链表逆置
ListNode l2 = mid.next;
while(l2 != null){
ListNode temp = l2;
l2 = l2.next;
temp.next = mid.next;
mid.next = temp;
}
//开始比对
ListNode scan = head;
l2 = mid.next;
//若长度为奇数 此时的mid指向前半段最后一个元素 如链表为[1,2,3,4],此时mid指向2
if(length % 2 == 0){
while(scan != mid.next){
if(scan.val != l2.val)
return false;
scan = scan.next;
l2 = l2.next;
}
return true;
}else{
//若长度为偶数 此时的mid指向中间元素如链表为[1,2,3],此时mid指向2
while(scan != mid){
if(scan.val != l2.val)
return false;
scan = scan.next;
l2 = l2.next;
}
return true;
}
}
}
总结
原地逆置和双指针是单链表题目中非常好用的方法,原地逆置使用头插法,双指针可以用来找倒数第n个元素等