版权声明:Please make the source marked https://blog.csdn.net/qq_31807385/article/details/86254979
题目:
给定一个链表的头结点是head,请判断该链表是否为回文结构
例如:
1->2->1,返回true
1->2->2->1,返回true
1->2->3,返回false
分析:
在链表问题中,时间复杂度一般都是O(n)的,所以链表的优化一般在空间复杂度上的优化,在笔试和面试中,面对链表的问题,我们的策略是不一样的,如果是在笔试中,不用考虑优化的问题,应该赶紧将当前的题目过掉,不需要考虑空间如何优化的问题,但是在面试的过程中,就应该建立在时间复杂度为O(1),尽可能的去降低额外的空间复杂度。
代码实现1(时间复杂度O(1),额外空间复杂度O(n)):
package com.isea.brush;
import java.util.Stack;
/**
* 判断一个链表是否是回文结构
* 实现思路:
* 使用一个辅助的栈结构,第一次遍历链表的时候将所有的元素都放入到栈中
* 第二次遍历链表的时候,依次取出栈中的元素,然后对比元素的值是否相等。
*
*/
public class Palindrome {
private class Node{
private int data;
private Node next;
public Node(int data){
this.data = data;
}
}
public static boolean isPalindrome(Node head){
Stack<Node> stack = new Stack<Node>();
Node cur = head;
while (cur != null){
stack.push(cur);
cur = cur.next;
}
while (head != null ){
if (head.data != stack.pop().data) {
return false;
}
head = head.next;
}
return true;
}
}
代码实现二:(时间复杂度O(1),额外空间复杂度O(n))
package com.isea.brush;
import java.util.Stack;
/**
* 判断一个链表是否是回文结构
* 实现思路:
* 使用一个辅助的栈结构,再使用两指针 ,一个快指针,一个慢指针,当快指针走完整个链表的时候,慢指针刚好来到链表。
* 中间的位置,此时从中间的位置开始将剩余链表中的元素放入到栈中;然后重头开始遍历链表,栈中的元素也依次弹出。
* 如果栈为空的时候,还没有出现元素不相等的情况的话,那么该链表是回文结构。
* 相比较于第一种方法,这样的方法能够节省一半的空间,但是额外空间复杂度还是O(n)的。
* 这里值得注意的是:无论链表的长度是奇数还是偶数,都需要保证慢指针在后半部分的起点
*
*/
public class Palindrome {
private class Node{
private int data;
private Node next;
public Node(int data){
this.data = data;
}
}
public static boolean isPalindrome(Node head){
if (head == null && head.next == null){
return true;
}
Node right = head.next;
Node cur = head;
while(cur.next != null && cur.next.next != null){
right = right.next;
cur = cur.next.next;
}
Stack<Node> stack = new Stack<Node>();
while(right != null){
stack.push(right);
right = right.next;
}
while(!stack.isEmpty()){
if (head.data != stack.pop().data){
return false;
}
head = head.next;
}
return true;
}
}
代码实现三:(时间复杂度O(1),额外空间复杂度O(1))
第三种实现方案,实现的思路是将后半部分的链表倒置,然后这个链表链表分别从两点开始遍历,对比元素是否是相等的,然后再将链表还原。