快慢指针判断链表回文结构


前言

在面试中碰到这种题,需要考虑空间复杂度


一、回文结构是什么?

就是一个链表关于中点对称,或者关于中心轴对称

二、方法不断改进

1.直接放入栈判断

1.1思路

  • 从头到尾遍历整个链表,将值放入栈中
  • 在从头遍历链表,每到一个节点就出栈一个值
  • 两个值相等就接着遍历
  • 如果不相等就直接返回不是回文结构
  • 如果直到栈为空了(或者头节点为空),就返回正确

1.2代码

	public static boolean isPalindrome1(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.value!=stack.pop().value) {
    
    
				return false;
				
			}else {
    
    
				head=head.next;
			}
		}
		return true;
		
	}

2.放一半到栈

1.1思路

  • 先让慢指针走一步,并且在快指针下个一个或者下两个为空的时候就停止
  • 这样就可以在长度为奇数时,慢指针最终指向中点,偶数时,慢指针指向两个中点的后一位
  • 接着将慢指针后面的全部入栈
  • 在从头遍历链表,每到一个节点就出栈一个值
  • 两个值相等就接着遍历
  • 如果不相等就直接返回不是回文结构
  • 如果直到栈为空了,就返回正确

1.2代码

public static boolean isPalindrome2(Node head) {
    
    
		if(head==null||head.next==null) {
    
    
			return true;
		}
		Node right = head.next;
		Node cur = head;
		Stack<Node> stack= new Stack<Node>();
		while(cur.next!=null&&cur.next.next!=null) {
    
    
		cur=cur.next.next;
		right=right.next;
		}
		while(right!=null) {
    
    
			stack.add(right);
			right=right.next;
		}
		while(!stack.empty()) {
    
    
			if(head.value!=stack.pop().value) {
    
    
				return false;
			}
			head = head.next;
		}
		return true;
		
	}

先改变后一半节点的指向,不用栈

1.1思路

  • 快慢指针同时出发,当在快指针下个一个或者下两个为空的时候就停止
  • 这样就可以在长度为奇数时,慢指针最终指向中点,偶数时,慢指针指向两个中点的前一位
  • 接着弄一个指针(Java引用),慢指针不变,快指针到慢指针的后面一个,新建的指针到快指针后面,用三个指针改变链表指向的套路改变后面的指向
  • 因为在改变完后,慢指针正好在最后一个节点,然后将快指针赋值到头节点
  • 然后快慢指针的值比较
  • 相等就继续遍历
  • 如果不想等就返回不是回文结构
  • 知道慢指针为空,就返回是回文结构
  • 但是要注意最后要将链表复原,不能改变链表的结构

1.2代码

	public static boolean isPalindrome3(Node head) {
    
    
		if(head == null || head.next == null) {
    
    
			return true;
		}
		Node n1=head;
		Node n2=head;
		while(n2.next!=null&&n2.next.next!=null){
    
    
			n1=n1.next;
			n2=n2.next.next;
		}
		n2=n1.next;
	    n1.next=null;
	    Node 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.value!=n2.value) {
    
    
				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;
	}

总结

在笔试可以直接就用第一种方法,在面试就需要用最后的方法。为了淘汰其他人

猜你喜欢

转载自blog.csdn.net/weixin_51422230/article/details/121578676