数据结构——判断一个链表是否为回文结构,时间复杂度O(N)空间复杂度为O(1)

作者:小 琛
欢迎转载,请标明出处
题目:
在这里插入图片描述
思路一:
该题目的最后一句话目的为降低难度,我们完全可以就这句话定义一个大小为900的数组,然后遍历该链表两次,第一次记录链表的每一个值并存入数组,并以一个变量count记录总数。第二次遍历的时候我们进行比对,数组倒着走,链表正常走,全部相等则为互文
在这里插入图片描述
注意事项:
1、因为我们遍历链表的条件是一个指针是否为空,所以记录数量的count的值在第一次遍历后要减一,count-1才是正确的数组下标
2、第二次遍历链表进行比对的时候让每比对一次count–
代码如下:

int ChkPalindrome1(PlistNode* head)
{
	if (head == NULL)
	{
		return 1;
	}
	PlistNode* n1 = head;
	PlistNode* n2 = head;
	int arr[900];
	int count = 0;
	while (n2 != NULL)
	{
		arr[count++] = n2->_date;
		n2 = n2->_next;
	}
	count--;
	n2 = NULL;
	while (n1 != NULL)
	{
		if (n1->_date != arr[count--])
			return 0;
		n1 = n1->_next;
	}
	return 1;
}

思路二:
当面试官要求不允许开辟数组进行存储的时候,我们思路一就行不通了,思路二有一定的难度,共进行如下操作
1、先寻找该链表的中点处,并记录
2、使用操作1记录的指针,逆置后一半的链表,并得到逆置后的新头,看下图
在这里插入图片描述
3、就n1和n2两个头开始遍历比较,以两者不为空为判断条件,全部相同则为互文,如果有一个不相同,则直接返回0

需要用到两个知识:寻找链表的中点,逆置一个链表。这两个知识点在上篇博文《数据结构——快慢指针》有讲述,需要的请回看,这里不进行讲述原文链接
除了逻辑之外,还要注意几个特殊情况:
(1)、当传入指针为空指针的时候
(2)、当传入的链表只有两个值的时候

int ChkPalindrome(PlistNode* head)
{
//当传入为空时
	if (head == NULL)
	{
		return 1;
	}
	//当传入的链表只有一个值
	if (head->_next == NULL)
		return 1;
	//当传入的链表只有两个值时
	if (head->_next->_next == NULL)
	{
		if (head->_date == head->_next->_date)
			return 1;
		else
			return 0;
	}
	
	//寻找中点
	PlistNode* n1 = head;
	PlistNode* n2 = head;
	while (n2 != NULL && n2->_next != NULL)
	{
		n1 = n1->_next;
		n2 = n2->_next;
		n2 = n2->_next;
	}
	n2 = head;

	//逆置后一半
	PlistNode* a1 = n1;
	PlistNode* a2 = a1->_next;
	PlistNode* a3 = a2->_next;
	a1->_next = NULL;
	while (a2 != NULL)
	{
		a2->_next = a1;
		a1 = a2;
		a2 = a3;
		if (a3 != NULL)
			a3 = a3->_next;
	}

	n1 = a1;
	a1 = a2 = a3 = NULL;
	while (n1 != NULL&&n2 != NULL)  //进行比对
	{
		if (n1->_date != n2->_date)
			return 0;
		n1 = n1->_next;
		n2 = n2->_next;
	}
	return 1;
}

感谢浏览

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值