您现在的位置是:首页 >其他 >【数据结构】--单链表力扣面试题⑥链表的回文结构网站首页其他

【数据结构】--单链表力扣面试题⑥链表的回文结构

姜暮、 2024-08-16 00:01:02
简介【数据结构】--单链表力扣面试题⑥链表的回文结构

题述:对于一个链表,请设计一个时间复杂度为o(n),额外空间复杂度为o(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度<=900

测试样例:

输入:1->2->2->1

输出:true

题目分析:

回文就是对称结构。题目所让求解的肯定是在单链表的前提下,要是双链表就很好求了,但是单链表的缺陷就是不能倒着走,只能正着走

一种想法是,创建数组大小900的数组,如int a[900],然后遍历链表,把每个节点的值都放入此数组中,用数组来判断回文。这样做oj上是能跑过的,但是不可行,因为这种方法的空间复杂度是o(n),因为你链表开多长你数组就得开多大去存储,这是一个侥幸方法。

正确的思路:

①、找链表的中间节点,偶数个结点就找后一个。至于怎么找,我之前代码有写过

②、将指向链表中间节点的指针(包括本身)后面的所有节点逆置,如果和中间节点之前的节点内容相同,那就符合回文结构

③、找到中间节点后,即使逆置,还可以使中间节点的前一个节点指向中间节点,可以不用解开(改变指向),因为不解开(不改变指向)也可以判断是否为回文结构,相反如果解开链表,会更麻烦。

 

//判断链表的回文结构
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

struct ListNode
{
	int val;
	struct ListNode* next;
};
//1、找中间节点的函数
struct ListNode* middleNode(struct ListNode* head)
{
	struct ListNode* slow, * fast;
	fast = slow = head;
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;
	}
	return slow;
}
//2、逆置链表的函数
struct ListNode* reverseList(struct ListNode* head)
{
	struct ListNode* n1, * n2, * n3;
	n1 = NULL;
	n2 = head;
	n3 = n2->next;
	while (n2)
	{
		n2->next = n1;
		n1 = n2;
		n2 = n3;
		if (n3)
		{
			n3 = n3->next;
		}
	}
	return n1;
}
bool chkPalindrome(struct ListNode* A)
{
	struct ListNode* mid = middleNode(A);//找到中间节点
	struct ListNode* rHead = reverseList(mid);//将中间节点(包括本身)后的节点翻转
	struct ListNode* curA = A;
	struct ListNode* curR = rHead;
	while (curA && curR)//因为对于有偶数个结点来说,curR会先碰到NULL,作为结束标志
	{//所以这里判断条件只写curR即可,在是回文的前提下。因为奇数节点时,curA和curR同时为空,
     //偶数是curR先为空
		if (curA->val != curR->val)
		{
			return false;
		}
		else
		{
			curA = curA->next;
			curR = curR->next;
		}
	}
	return true;
}
int main()
{
	struct ListNode* n1 = (struct ListNode*)malloc(sizeof(struct ListNode));
	struct ListNode* n2 = (struct ListNode*)malloc(sizeof(struct ListNode));
	struct ListNode* n3 = (struct ListNode*)malloc(sizeof(struct ListNode));
	struct ListNode* n4 = (struct ListNode*)malloc(sizeof(struct ListNode));
	struct ListNode* n5 = (struct ListNode*)malloc(sizeof(struct ListNode));

	n1->val = 1;
	n2->val = 2;
	n3->val = 3;
	n4->val = 2;
	n5->val = 1;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = n5;
	n5->next = NULL;

	int Istrue = chkPalindrome(n1);
	printf("该链表是否为回文结构:(1真/0假)%d", Istrue);

	return 0;
}

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。