请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
提示:
链表中节点数目在范围[1, 105] 内
0 <= Node.val <= 9
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
方法 1
转成数组然后双指针,因为链表的特点就是无法从后向前迭代,所以需要转成数组按索引分别从前向后和从后向前查找
注意:Integer中==和equal的区别
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){
return true;
}
List<Integer> nodes = new ArrayList<>();
while(head != null){
nodes.add(head.val);
head = head.next;
}
int left = 0, right = nodes.size() - 1;
while(left < right){
//这里一定要注意,java的Integer的自动装箱走的是Integer.valueOf()方法,该方法-128~127是走的IntegerCache.cache[]数组
//只要数值相等,就对应同一个Integer对象,但是不在此范围内的就是new出来的Integer,用==比较的话就为false了
if(!nodes.get(left).equals(nodes.get(right))){
return false;
}
++left;
--right;
}
return true;
}
}
方法2.1 修改链表不还原
快慢指针——需要修改链表,对前半部分或者后半部分进行逆序
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){
return true;
}
ListNode slow = head, fast = head, pre = null;
//找中点时顺便反转前半段链表
while(fast != null && fast.next != null){
fast = fast.next.next;
ListNode tmp = slow.next;
slow.next = pre;
pre = slow;
slow = tmp;
}
//奇数个结点,slow会指向最中间的结点
if(fast != null){
slow = slow.next;
}
while(pre != null){
if(pre.val != slow.val){
return false;
}
pre = pre.next;
slow = slow.next;
}
return true;
}
}
方法2.2 修改并还原链表
比较时进行链表的还原:
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){
return true;
}
ListNode slow = head, fast = head, pre = null;
//找中点时顺便反转前半段链表
while(fast != null && fast.next != null){
fast = fast.next.next;
ListNode tmp = slow.next;
slow.next = pre;
pre = slow;
slow = tmp;
}
ListNode recoverPre = slow;
//奇数个结点,slow会指向最中间的结点
if(fast != null){
slow = slow.next;
}
while(pre != null){
if(pre.val != slow.val){
return false;
}
slow = slow.next;
//还原链表
ListNode tmp = pre.next;
pre.next = recoverPre;
recoverPre = pre;
pre = tmp;
}
return true;
}
}