一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情。
周六的痛苦面具加班日...
回文链表
该题出自力扣的234题 —— 回文链表【简单题】,虽然是道简单题,但是如果考虑复杂度的话就不简单了
审题
给你一个单链表的头节点
head,请你判断该链表是否为回文链表。如果是,返回true;否则,返回false。
- 该题的题意也很简单,主要就集中在回文链表里面 —— 也就是对称链表。[1,2,4,5,4,2,1]从头遍历和从尾遍历都一样的就属于对称链表
- 解法很多:
- 解法一: List 集合 + 双指针
- 利用一个List 集合去装载整个链表的节点
- 遍历链表,依次加入集合
- 利用双指针去校验是否为回文链表(头尾指针分别开始,如果值不相等,则直接返回false)
- 时间复杂度为O(n),因为需要遍历链表
- 空间复杂度为O(n),因为需要开辟一个集合去装载
- 解法二: 快慢指针 + 链表反转 + 对撞指针
- 利用快慢指针,使慢指针走到链表的一半
- 在慢指针的同时,利用反转链表,使得慢指针的前半部分链表反转
- 最后获得一个链表的结构 —— 指针的前半部分是反转的,与后半部分行成反链
- 利用对撞指针如解法一 一样校验是否为回文链表
- 之所以使用快慢指针定位对称中间值,是因为如果要直接反转整条练的话,因为引用的是地址,所以需要额外开辟一条链去存储
- 时间复杂度还是O(n)
- 空间复杂度为O(1),优化了空间复杂度
- 解法一: List 集合 + 双指针
编码
- 双指针 + List集合
List<Integer> list = new ArrayList<>();
public boolean isPalindrome(ListNode head) {
while(head != null){
list.add(head.val);
head = head.next;
}
for (int i = 0,j = list.size()-1;i<=j;i++){
if (!list.get(i).equals(list.get(j)))return false;
j--;
}
return true;
}
- 双指针 + 快慢指针 + 链表反转
public boolean isPalindrome(ListNode head) {
ListNode pre = null,fast = head,slow = head;
while (fast != null && fast.next != null){
ListNode next = slow.next;
if (pre != null){
slow.next = pre;
}
pre = slow;
fast = fast.next.next;
slow = next;
}
if (fast != null)slow = slow.next;
while (slow != null){
if (slow.val != pre.val)return false;
slow = slow.next;
pre = pre.next;
}
return true;
}