234. 回文链表
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
思路与代码(java)
方法一,双循环,(比较容易懂)
简单来说就是把链表的元素都装到数组,利用数组可以随机访问的特性,双指针,一个在头加加,一个在尾减减,不相同直接 retrun false
。
1 | 2 | 3 | 2 | 1 |
---|---|---|---|---|
头指针 | —> | <— | 尾指针 |
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head==null || head.next==null) {
return true;
}
java.util.ArrayList<Integer> arr = new java.util.ArrayList<Integer>();
//申请一个容器,然后把元素都放到数组中
while(head!=null) {
arr.add(head.val);
head = head.next;
}
int i = 0;
int j = arr.size()-1;
//用i和j两个指针,一个往后,一个往前,不断迭代
//如果i的值不等于j说明不是回文,反之是回文
while(i<j) {
if(arr.get(i).compareTo(arr.get(j))!=0) {
return false;
}
++i;
--j;
}
return true;
}
}
执行用时 :4 ms, 在所有 Java 提交中击败了23.46%的用户
内存消耗 :40.7 MB, 在所有 Java 提交中击败了97.70%的用户
方法二,快慢指针,(有点难度)
使用快慢两个指针找到链表中点,慢指针每次前进一步,快指针每次前进两步。在慢指针前进的过程中,同时修改其 next 指针,使得链表前半部分反序。最后比较中点两侧的链表是否相等。
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true;
}
ListNode prev = null;
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
ListNode next = slow.next;
slow.next = prev;
prev = slow;
slow = next;
}
if (fast != null) {
slow = slow.next;
}
while (slow != null) {
if (slow.val != prev.val) {
return false;
}
slow = slow.next;
prev = prev.next;
}
return true;
}
}
执行用时 :1 ms, 在所有 Java 提交中击败了99.53%的用户
内存消耗 :41.5 MB, 在所有 Java 提交中击败了97.32%的用户
方法三,递归,(有点难度)
class Solution {
private ListNode frontPointer;
private boolean recursivelyCheck(ListNode currentNode) {
if (currentNode != null) {
if (!recursivelyCheck(currentNode.next)) return false;
if (currentNode.val != frontPointer.val) return false;
frontPointer = frontPointer.next;
}
return true;
}
public boolean isPalindrome(ListNode head) {
frontPointer = head;
return recursivelyCheck(head);
}
}