题目:
编写一个函数,检查输入的链表是否是回文的。
示例 1:
输入: 1->2
输出: false
示例 2:输入: 1->2->2->1
输出: true进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:
-
将链表的数据复制到数组集合中,再用双指针判断是否为回文
- 时间复杂度:O(n),其中 n 指的是链表的元素个数。
第一步: 遍历链表并将值复制到数组中,O(n)。
第二步:双指针判断是否为回文,执行了 O(n/2) 次的判断,即 O(n)。
总的时间复杂度:O(2n) = O(n)。 - 空间复杂度:O(n),其中 n 指的是链表的元素个数,我们使用了一个数组列表存放链表的元素值
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
List<Integer> vals = new ArrayList<Integer>();
//将链表中的数据复制到数组集合中
ListNode temp = head;
while(temp != null){
vals.add(temp.val);
temp = temp.next;
}
//使用双指针判断回文
int front = 0;
int back = vals.size() - 1;
while(front < back){
if(!vals.get(front).equals(vals.get(back))){
return false;
}
front ++;
back --;
}
return true;
}
}
-
找到前半部分链表的尾节点,反转后半部分链表,判断是否回文,恢复链表.
- 时间复杂度O(n)
- 空间复杂度O(1)
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null) {
return true;
}
// 找到前半部分链表的尾节点并反转后半部分链表
ListNode firstHalfEnd = endOfFirstHalf(head);
ListNode secondHalfStart = reverseList(firstHalfEnd.next);
// 判断是否回文
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while (result && p2 != null) {
if (p1.val != p2.val) {
result = false;
}
p1 = p1.next;
p2 = p2.next;
}
// 还原链表并返回结果
firstHalfEnd.next = reverseList(secondHalfStart);
return result;
}
//还原链表
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
//找到链表的前半部分的尾节点
private ListNode endOfFirstHalf(ListNode head) {
//定义快慢指针
ListNode fast = head;
ListNode slow = head;
//慢指针一次走一步,快指针一次走两步,快慢指针同时出发。当快指针移动到链表的末尾时,慢指针恰好到链表的中间
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}