链表(二)三种方式判断链表是否为回文结构额外空间O(1)

判断一个链表是否为回文结构

(只看黑体字和代码即可)

思路一:把链表节点依次压入栈中,然后依次从栈中拿出节点与链表节点进行比较

// 额外空间复杂度O(n)借助了栈结构
	public static boolean function1(Node head) {
		Stack<Node> a = new Stack<Node>();
		Node help = head;// 复制了一个头节点,指向后面的位置,指的位置在内存中是一致的
		while (help != null) {
			a.push(help);
			help = help.next;
		}
		while (!a.isEmpty()) {
			if (head.value != a.pop().value)
				return false;
			head = head.next;
		}
		return true;

	}

思路二:设置两个指针,一个为快指针(2V),一个为慢指针(V)。把中间及以后位置压入栈

(两个指针初始位置都是head,当链表节点数为奇数时,如1 2 3 4 5快指针走到位置5,慢指针在位置3。当节点个数为偶数时,

1 2 3 4 5 6,快指针走到5,慢指针走到3.

将3 4 5 6节点压入栈中

然后把栈顶开始与head及next进行比较)

// 借助一半的空间,指针走到一半,把剩下的部分入栈,注意特殊部分的处理,可能head的就是个空值

	public static boolean function2(Node head) {
		if(head==null||head.next==null) return true;
		Node fast = head;
		Node slow = head;
		
		Stack<Node> a = new Stack<Node>();
		while (fast.next!=null&&fast.next.next != null) {
			fast = fast.next.next;
			slow = slow.next;
		}
		while (slow != null) {
			a.push(slow);
			slow = slow.next;
		}
		while (!a.isEmpty()) {
			if (a.pop().value != head.value)
				return false;
			head = head.next;

		}
		return true;
	}

 


进阶:要求链表长度为n时,时间复杂度为O(n),额外空间复杂度为O(1)

思路:同快慢指针,快指针(fast)停止前进时,慢指针(slow)在中间位置(奇数--中间位置,偶数--中间两个位置中的靠前位置)

以slow为头节点,将slow节点以后的进行链表反转

然后从两边向中间遍历。直到从head位置的链表遍历到next为null停止。

返回结论前,将刚刚翻转的一段再翻转回来

代码:

public static boolean function3(Node head) {
		boolean ans=true;
		if(head==null||head.next==null) return true;
		Node fast=head;
		Node slow=head;
		while(fast.next!=null&&fast.next.next!=null) {
			fast=fast.next.next;
			slow=slow.next;			
		}
		//此时slow停留在中间位置,如果是偶数,则是中间位置中的前一个位置
		//while后,fast为链表的尾部
		 while(fast.next!=null) fast=fast.next;
		Node h2=reverse(slow);//翻转
		//slow.next=null;
		//开始遍历,查询
		 while(head!=null){
			if(h2.value!=head.value)
				{ans=false;break;}
			h2=h2.next;
			head=head.next;
		}
		 reverse(fast);//把刚刚翻转过的再转回来,参数:传入头节点
		 return ans; 
	}
public static Node reverse(Node head) {
		Node pre=null;
		Node next=null;
		while(head!=null)
		{
			next=head.next;
			head.next=pre;
			pre=head;
			head=next;//下移一位
		}
		return pre;
	}

 

(以下分析可略过)

【奇】

  ———————————————————————————

【偶】从两边对比,遇到3位置时由于其next=null,停止。

当快fast指针停下的时候,还未指到最后一个节点,手动将其指到最后一个节点:

两边开始遍历,A:head为头节点,B:fast为头节点

到head遍历完3位置后停止。(head.value==null)

 


全部代码:

package Node;

import java.util.Stack;

import Node.ReverseList.Node;

//判断链表是否为回文
public class isPalindrome {
	// 链表结构
	public static class Node {
		int value;
		Node next;
		Node(int a) {
			this.value = a;
		}
	}
	// 额外空间复杂度O(n)借助了栈结构
	public static boolean function1(Node head) {
		Stack<Node> a = new Stack<Node>();
		Node help = head;// 复制了一个头节点,指向后面的位置,指的位置在内存中是一致的
		while (help != null) {
			a.push(help);
			help = help.next;
		}
		while (!a.isEmpty()) {
			if (head.value != a.pop().value)
				return false;
			head = head.next;
		}
		return true;

	}
	// 借助一半的空间,指针走到一半,把剩下的部分入栈,注意特殊部分的处理,可能head的就是个空值

	public static boolean function2(Node head) {
		if(head==null||head.next==null) return true;
		Node fast = head;
		Node slow = head;
		
		Stack<Node> a = new Stack<Node>();
		while (fast.next!=null&&fast.next.next != null) {
			fast = fast.next.next;
			slow = slow.next;
		}
		while (slow != null) {
			a.push(slow);
			slow = slow.next;
		}
		while (!a.isEmpty()) {
			if (a.pop().value != head.value)
				return false;
			head = head.next;

		}
		return true;
	}
	public static boolean function3(Node head) {
		boolean ans=true;
		if(head==null||head.next==null) return true;
		Node fast=head;
		Node slow=head;
		while(fast.next!=null&&fast.next.next!=null) {
			fast=fast.next.next;
			slow=slow.next;			
		}
		//此时slow停留在中间位置,如果是偶数,则是中间位置中的前一个位置
		//fast为链表的尾部
		 while(fast.next!=null) fast=fast.next;
		Node h2=reverse(slow);
		//slow.next=null;
		//开始遍历,查询
		 while(head!=null){
			if(h2.value!=head.value)
				{ans=false;break;}
			h2=h2.next;
			head=head.next;
		}
		 reverse(fast);//把刚刚反转过的再转回来
		 return ans; 
	}
	public static Node reverse(Node head) {
		Node pre=null;
		Node next=null;
		while(head!=null)
		{
			next=head.next;
			head.next=pre;
			pre=head;
			head=next;//下移一位
		}
		return pre;
	}

	public static void main(String[] args) {
		
		Node head = null;
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		System.out.print(function2(head) + " | ");
		 System.out.println(function3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		System.out.print(function2(head) + " | ");
		 System.out.println(function3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		System.out.print(function2(head) + " | ");
		System.out.println(function3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(1);
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		System.out.print(function2(head) + " | ");
		System.out.println(function3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(3);
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		System.out.print(function2(head) + " | ");
		System.out.println(function3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(1);
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		System.out.print(function2(head) + " | ");
		System.out.println(function3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(3);
		head.next.next.next = new Node(1);
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		System.out.print(function2(head) + " | ");
		System.out.println(function3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(2);
		head.next.next.next = new Node(1);
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		
		  System.out.print(function2(head) + " | ");
		 System.out.println(function3(head) + " | ");
		 
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(3);
		head.next.next.next = new Node(4);
		head.next.next.next.next = new Node(5);
		printLinkedList(head);
		System.out.print(function1(head) + " | ");
		
		System.out.print(function2(head) + " | ");
		System.out.println(function3(head) + " | ");
		 
	printLinkedList(head);
		System.out.println("=========================");

	}

	private static void printLinkedList(Node head) {
		while (head != null) {
			System.out.print(head.value + ",");
			head = head.next;
		}
		System.out.println();
	}

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值