【LeetCode】234.回文链表

问题描述

给你一个单链表的头节点 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) 空间复杂度解决此题?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

快慢指针

首先我并不认为这是一个简单题。。。。。那我来说一下我的思路吧:

题目要求了空间复杂度和时间复杂度,这就比较难搞了。所以我们只能扫描一遍,并且要使用常数级的空间。

我们通过快慢指针来对这个链表分成两段,慢指针每次走一步,快指针每次走两步,当快指针为空时,慢指针恰好走到了链表的中间,那么就可以把这个链表分成两段了。当然在这个过程注意一下链表长度是奇数还是偶数,处理稍有不同。如果此时直接比较,由于两段链表的元素顺序是相反的,所以还是不行。因此我们在分段时就通过slow把前半段链表倒置。链表倒置还是比较简单的吧,前面也遇到过。一般都是设置一个哑结点,只不过这里这样总是报奇奇怪怪的错误:heap-use-after-free,实在是不知道为啥。后来我想了想,若通过设置哑结点来倒置,那么倒置完成的最后一个结点的next值是指向自身的。。。(当然我把这个改正了还是会报错)。这里提供一个新的思路,哑结点我们不是new出来了,而是一开始为nullptr,当第一个结点出现时赋值就行,以后每次都被赋值为第一个结点就好了。。具体可以看下面的代码了。

代码:

//判断一个链表是否是回文链表
class Solution {
public:
	bool isPalindrome(ListNode* head) {
		if (head == nullptr || head->next == nullptr) {
			return true;
		}
		ListNode* dumb = nullptr;
		ListNode* slow = head;
		ListNode* fast = head;
		ListNode* pre = nullptr;
		while (fast != nullptr && fast->next != nullptr) {
			fast = fast->next;
			fast = fast->next;
			pre = slow;
			slow = slow->next;
			pre->next = dumb;
			dumb = pre;
		}
		if (fast == nullptr) {//长度为偶数,slow指向后半截第一个元素,pre指向前半截最后一个元素
			fast = slow;
			slow = dumb;
		}
		else if (fast->next == nullptr) {//长度为奇数,slow指向中间的元素
			fast = slow->next;
			slow = dumb;
		}
		while (fast != nullptr) {
			if (fast->val != slow->val) {
				return false;
			}
			slow = slow->next;
			fast = fast->next;
		}
		return true;
	}
};

执行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值