LeetCode初级算法25:回文链表

🐕 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。

如果是,返回 true ;否则,返回 false 。

示例 1:

输入:head = [1,2,2,1]
输出:true

示例 2:

输入:head = [1,2]
输出:false

提示:

链表中节点数目在范围[1, 105] 内
0 <= Node.val <= 9

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

🐖思路一:

快慢指针 慢指针一次走一步 快指针一次走两步
slow指针 后半段入栈 之后弹出再与前半段比较
如果直到栈为空都相等 证明是回文

上代码

public static boolean isPalindrome(ListNode head) {
    	if(head == null) {
    		return true;
    	}
    	//快慢指针 慢指针一次走一步 快指针一次走两步
    	ListNode slow = head;
    	ListNode fast = head;
    	while(fast.next != null && fast.next.next != null) {
    		slow = slow.next;
    		fast = fast.next.next;
    	}
    	//现在slow指针已经到达中点位置 考虑入栈
    	Stack<ListNode> stack = new Stack<>();
    	while(slow != null) {
    		stack.push(slow);
    		slow = slow.next;
    	}
    	//入栈完毕 接下来出栈比较
    	while(!stack.isEmpty()) {
    		if(head.val != stack.pop().val) {
    			return false;
    		}
    		head = head.next;
    	}
    	return true;
    }

在这里插入图片描述

🐀思路二:双指针 未复原 只判断版本

快慢指针 慢指针一次走一步 快指针一次走两步
修改slow后半段指针 指向
从尾巴和 head 依次对比 如果不相等 返回 false

上代码

public static boolean isPalindrome_V2(ListNode head) {
    	if(head == null) {
    		return true;
    	}
    	ListNode slow = head;
    	ListNode fast = head;
    	while(fast.next != null && fast.next.next != null) {
    		fast = fast.next.next;
    		slow = slow.next;
    	}
    	//如果此时链表只有一个数时 return true
    	if(slow.next == null) {
    		return true;
    	}
    	//先记录temp 为 slow的next ,让slow的next 指向 null
    	// 让tempNext 为temp的next 让 temp 的next 指向 slow
    	ListNode temp = slow.next;
    	slow.next = null;
    	ListNode tempNext = temp.next;
    	while(temp != null) {
    		temp.next = slow;
    		slow = temp;
    		temp =tempNext ;
    		tempNext = tempNext == null ? null:tempNext.next;
    	}
    	//此时slow就是尾结点
    	while(slow != null && head != null) {
    		if(head.val != slow.val) {
    			return false;
    		}
    		slow = slow.next;
    		head = head.next;
    	}
    	return true;
    }

在这里插入图片描述

🐇 思路三:双指针 判断且复原版本

双指针 然后反转后半段链表 再从两端一一对比
如果途中有不相等 记录flag = false
如果整个途中没有不相等的 flag = true
然后要把链表还原

上代码

public static boolean isPalindrome_V3(ListNode head) {
    	if(head == null) {
    		return true;
    	}
    	ListNode slow = head;
    	ListNode fast = head;
    	while(fast.next != null && fast.next.next != null) {
    		fast = fast.next.next;
    		slow = slow.next;
    	}
    	//如果此时链表只有一个数时 return true
    	if(slow.next == null) {
    		return true;
    	}
    	ListNode mid = slow;//待会复原要用到
    	
    	//先记录temp 为 slow的next ,让slow的next 指向 null
    	// 让tempNext 为temp的next 让 temp 的next 指向 slow
    	ListNode temp = slow.next;
    	slow.next = null;
    	ListNode tempNext = temp.next;
    	while(temp != null) {
    		temp.next = slow;
    		slow = temp;
    		temp =tempNext ;
    		tempNext = tempNext == null ? null:tempNext.next;
    	}
    	//此时slow就是尾结点
    	ListNode tail = slow;	//待会复原要用到
    	
    	boolean flag = true;
    	while(slow != null && head != null) {
    		if(head.val != slow.val) {
    			flag = false;
    			break;
    		}
    		slow = slow.next;
    		head = head.next;
    	}
    	/*
    	 开始复原后半段
    	 记录 tail.next 为 pre
    	 pre.next 为 prePre
    	 让tail的next 指向 null
    	 */
    	ListNode pre = tail.next;
    	ListNode prePre  = pre.next;
    	tail.next = null;
    	
    	while(tail != mid) {
    		pre.next = tail;
    		tail = pre;
    		pre = prePre;
    		prePre = prePre == null ? null : prePre.next;
    	}
    	return flag;
    }

在这里插入图片描述

🐘思路四:递归判断

这里扯一个点:递归打印单向链表…

public static void printNodes(ListNode head) {
    	if(head == null) {
    		return;
    	}
    	printNodes(head.next);
    	System.out.println(head.val);
    }

上代码

static ListNode temp;
    public static boolean isPalindrome_V4(ListNode head) {
    	temp = head;	// temp总是按顺序记录前半段
    	return check(head);
    }
    public static boolean check(ListNode head) {
    	if(head == null) {
    		return true;
    	}
    	// head 会递归至 结尾再判断
    	boolean res = check(head.next) && (temp.val == head.val);
    	temp = temp.next;
    	return res;
    }

在这里插入图片描述

这个递归也是挺六的~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值