如何判断一个单链表是否为回文链表?
回文链表
LeetCode 234. Palindrome Linked List
例 1:
1 2
| Input: 1->2 Output: false
|
例 2:
1 2
| Input: 1->2->2->1 Output: true
|
提升:
时间复杂度为 O (n),空间复杂度为 O (1).
解法一
直接将链表进行 反转 ,然后将新的反转链表与原链表进行比较,这种思路最为简单粗暴。
此种解法的时间复杂度为 O (n),空间复杂度为 O (n).
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
class Solution { public boolean isPalindrome(ListNode head) { if(head == null){ return true; } ListNode newCurr = null; ListNode newPrev = null; ListNode curr = head; while(curr != null){ newCurr = new ListNode(curr.val); newCurr.next = newPrev; newPrev = newCurr; curr = curr.next; } ListNode p1 = newCurr; ListNode p2 = head; while(p2 != null && p2 != null){ if(p2.val != p1.val){ return false; } p1 = p1.next; p2 = p2.next; } return true; } }
|
LeetCode 性能测试:
Runtime: 3 ms, faster than 24.01% of Java online submissions forPalindrome Linked List.
解法二
为了降低空间复杂度到 O (1),我们可以只对链表的后半部分直接反转,然后将反转后的后半部分与前半部分进行比较。
如何对后半部分进行反转呢?这就涉及到我们前面的 如何找到中间节点 的方法,使用快慢指针,先找到中间节点,然后从中间节点开始反转。
需要注意的是,在进行比较时,要以后半部分为基准进行遍历来比较,例如在链表长度位偶数的情况下:
A -> B -> C -> C -> B -> A
反转得到 A -> B -> C -> C <- B <- A
,以前半部分为基准的话,会出现 null 指针的异常。
此种解法的时间复杂度为 O (n),空间复杂度为 O (1).
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
class Solution { public boolean isPalindrome(ListNode head) { if(head == null){ return true; } ListNode slow = head; ListNode fast = head; for(ListNode curr = slow; slow != null; ){ if(fast == null || fast.next == null){ break; }else{ fast = fast.next.next; } slow = slow.next; } ListNode prev = null; ListNode curr = slow; ListNode next = null; while(curr != null){ next = curr.next; curr.next = prev; prev = curr; curr = next; } ListNode p1 = head; ListNode p2 = prev; while(p2 != null){ if(p1.val != p2.val){ return false; } p1 = p1.next; p2 = p2.next; } return true; } }
|
LeetCode 性能测试:
Runtime: 1 ms, faster than 93.05% of Java online submissions forPalindrome Linked List.
解法三
解法三比较巧妙,不容易想到。思路如下:
- 定义左右两个指针,左指针向右移动,” 右指针向左移动”,对比左右两个指针是否配置。
- 我们这里是单链表,右指针怎么向左移动呢?这里通过递归的方式,当递归函数一层一层返回时,变相地实现了” 右指针左移” 的思路。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
class Solution { private ListNode head; private ListNode left; public boolean isPalindrome(ListNode head1) { head = head1; return isPalindromeUtil(head1); } private boolean isPalindromeUtil(ListNode right){ left = head; if (right == null){ return true; } boolean isp = isPalindromeUtil(right.next); if (isp == false){ return false; } boolean isp1 = (right.val == left.val);
left = left.next; return isp1; } }
|
LeetCode 性能测试:
Runtime: 3 ms, faster than 22.70% of Java online submissions forPalindrome Linked List.
相关练习
参考资料