1.借助栈实现判断一个链表是否为回文结构 【题目】 给定一个链表的头节点head,请判断该链表是否为回文结构。 例如: 1->2->1,返回true。
1->2->2->1,返回true。 15->6->15,返回true。 1->2->3,返回false。
进阶: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1)。
1.1 思路
栈是一个先进后出的结果,如果一个链表是回文的话 那么势必 出栈的val 等于 正序的val
时间复杂度:O(n)
空间复杂度:O(n)
1.2 code
public boolean isPalindrome(ListNode head) {
if(head == null){
return true;
}
Stack<ListNode> stack = new Stack<>();
ListNode cur = head;
while(cur != null){
stack.push(cur);
cur = cur.next;
}
while(head!=null){
if(head.val != stack.pop().val){
return false;
}
head = head.next;
}
return true;
}
2.快慢指针+栈
2.1 思路
快慢指针就是定义两个节点都指向head节点 fast节点每次走两步,slow节点每次走一步。当fast节点走到尾部,slow节点必定在链表的中间位置(如果是奇数个 在中间 ,偶数的话在中间位置的左边)。
将后半部分的节点依次push到栈中。然后依次比较栈中pop的元素和head节点依序比较,如果相同,为回文结构,否则的话,不是回文结构。
时间复杂度:O(n)
空间复杂度:O(n/2)
2.2 code
//2.快慢指针+栈
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){
return true;
}
ListNode fastNode = head;
ListNode slowNode = head.next;
//快慢指针
while(fastNode.next != null && fastNode.next.next != null){
slowNode = slowNode.next;
fastNode = fastNode.next.next;
}
// 剩余的一般节点添加进栈中
Stack<ListNode> stack = new Stack<>();
while(slowNode != null){
stack.push(slowNode);
slowNode = slowNode.next;
}
//比较stack 和 head 前一半是否相同
while(!stack.isEmpty()){
if(head.val != stack.pop().val){
return false;
}
head = head.next;
}
return true;
}
3.快慢指针+逆序链表
3.1 思路
通过第一种和第二种 虽然space逐渐减半,但是对于大数据量的链表,如果能将空间复杂度减到O(1)无疑是最优的答案,因此,先用快慢指针找到mid点 然后将mid之后的链表反转和mid之前的链表元素进行比较,如果不相等 存储res结果退出,否则的话 比较,最后 将逆序的部分在逆序回来。
时间复杂度:O(n)
空间复杂度:O(1)
3.2 code
//反转 比较 反转 time O(n) space : O(1)
public boolean isPalindrome3(ListNode head) {
if(head == null || head.next == null) {
return true;
}
ListNode n1 = head;
ListNode n2 = head;
//快慢指针
while(n2.next!=null && n2.next.next!=null){
n1 = n1.next;
n2 = n2.next.next;
}
//后半部分链表反转
n2 = n1.next;
n1.next = null;
ListNode n3 = null;
while(n2!=null){
n3 = n2.next;
n2.next = n1;
n1 = n2;
n2 = n3;
}
//比较
n3 = n1;
n2 = head;
boolean res = true;
while(n1!=null && n2 !=null){
if(n1.val!=n2.val){
res = false;
break;
}
n1 = n1.next;
n2 = n2.next;
}
//反转回来
n1 = n3.next;
n3.next = null;
while(n1!=null){
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}