IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 面试算法 牛客题目 判断一个链表是否为回文结构 -> 正文阅读

[数据结构与算法]面试算法 牛客题目 判断一个链表是否为回文结构

1.题目: ?判断一个链表是否为回文结构
描述
给定一个链表,请判断该链表是否为回文结构。
回文是指该字符串正序逆序完全一致。
数据范围: 链表节点数 0 \le n \le 10^50≤n≤10?
?链表中每个节点的值满足 |val| \le 10^7∣val∣≤10?


2.算法:
//1.暴力算法:全部反转 ?
//2.双指针算法 半边链表反转?


算法思想:

1.暴力算法:新建一个相同的链表? 反转他? 比较值的大小

2.双指针算法 半边链表反转 :

  • 空间复杂度:O(n)O(n)O(n),记录链表元素的辅助数组

知识点:双指针

双指针指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针(特殊情况甚至可以多个),两个指针或是同方向访问两个链表、或是同方向访问一个链表(快慢指针)、或是相反方向扫描(对撞指针),从而达到我们需要的目的。

思路:

在数组中,我们可以借助双指针,一个从前往遍历前一半数组,另一个从后往前遍历后一半数组,依次比较值。链表中如果我们要用这样的思想,左指针从前往后很容易,直接的链表的遍历就可以了。但是右指针是真的没有办法从尾巴往前走,要是链表后半段的指针是逆序的就好了。

怎么样能让链表后半段的指针反过来,将后半段链表整体反转不就行了吗?如果我们将后半段链表整体反转,那么相当于后半段就是从末尾指向中间,就可以实现后半段的逆序遍历——按照指针直接走就可以了。

具体做法:

  • step 1:遍历链表,统计链表的长度。
  • step 2:将长度除2,遍历这么多位置,找到链表的中点。
  • step 3:从中点位置开始,对链表后半段进行反转。
  • step 4:与方法二类似,双指针左指针指向链表开头,右指针指向链表尾,此时链表前半段是正常的,我们也可以正常遍历,但是链表后半段所有指针都被我们反转逆序,因此我们可以从尾节点往前遍历。
  • step 5:依次比较对应位置的元素值是否相等。

3.双指针找中点(推荐使用)

思路:

上述方法三找中点,我们遍历整个链表找到长度,又遍历长度一半找中点位置。过程过于繁琐,我们想想能不能优化一下,一次性找到中点。

我们首先来看看中点的特征,一个链表的中点,距离链表开头是一半的长度,距离链表结尾也是一半的长度,那如果从链表首遍历到链表中点位置,另一个每次遍历两个节点的指针是不是就到了链表尾,那这时候我们的快慢双指针就登场了:

具体做法:

  • step 1:慢指针每次走一个节点,快指针每次走两个节点,快指针到达链表尾的时候,慢指针刚好到了链表中点。
  • step 2:从中点的位置,开始往后将后半段链表反转。
  • step 3:按照方法三的思路,左右双指针,左指针从链表头往后遍历,右指针从链表尾往反转后的前遍历,依次比较遇到的值


4.代码:

/*************************************************
作者:She001
时间:2022/9/30
题目:  判断一个链表是否为回文结构
描述
给定一个链表,请判断该链表是否为回文结构。
回文是指该字符串正序逆序完全一致。
数据范围: 链表节点数 0 \le n \le 10^50≤n≤10 
 链表中每个节点的值满足 |val| \le 10^7∣val∣≤10 



***************************************************/
//算法:
//1.暴力算法:全部反转  
//2.双指针算法 半边链表反转 

#include<bits/stdc++.h>
using namespace std;
typedef struct node
{
	int i;
	node *next;	
}; 


void print(node * head)//打印链表 
{
	node* pp= head;//复制头节点 
	while(pp!=NULL)//判断这个节点是否为空  链表是否结束 
	{
		cout<<pp->i<<"  ";
		pp=pp->next;//指向下一个 
	}
	cout<<endl;
	
}



int lianbiao_num(node * head)//函数的作用 返回链表的个数
{
	int i=0;
	node* pp=head;
	while(pp!=NULL)
	{
		i++;
		pp=pp->next;	
	}
	//cout<<"链表中节点的个数: "<<i<<endl;
	return i;	
} 


node * reverseList(node* head)//翻转链表 
{
	if(head==NULL)
	{
		return NULL;	
	}	
	node * a = head;
	node * b = NULL;
	while(a!=NULL)
	{
		node * c = a->next;
		a->next=b;
		b=a;
		a=c;
	}
	return b;	
} 


//1.暴力算法:全部反转  
//
bool  fangfa_1(node * head)
{
	if(head==NULL)//链表为空返回 是回文 
	{
		return true;
	}
	if(lianbiao_num(head)==1)//链表只有一个 返回是回文 
	{
		return true;
	}
	node* a1=head;//指针遍历 链表 
	node* head2=new node;//建立的另外节点的头节点 
	node* hh=head2;//第二个节点的指针 方便连接 
	while(a1!=NULL)//建立第二个链表 
	{
		hh->i=a1->i;//第二个链表赋值 
		a1=a1->next;//指向下一个节点 
		if(a1==NULL)//判断下一个 节点是否空 
		{
			hh->next=NULL;
		}
		else
		{
			hh->next = new  node;
			hh=hh->next;
		}
	}
	
	node * h1= reverseList(head2);//翻转第二个链表 
	hh=h1; 
	a1=head;
	while(hh!=NULL && a1!=NULL)
	{
		if((hh->i) != (a1->i))
		{	
			while(h1!=NULL)//销毁建立的链表 
			{
				node * p=h1;
				h1=h1->next;
				delete p;
			}
			return false;
		}
		hh=hh->next;
		a1=a1->next;
	}
	
	while(h1!=NULL)//销毁建立的链表 
	{
		node * p=h1;
		h1=h1->next;
		delete p;
	}
	return true;
}



//2.双指针算法 半边链表反转 
bool  fangfa_2(node* head)
{
	if(head==NULL)//链表为空返回 是回文 
	{
		return true;
	}
	if(lianbiao_num(head)==1)//链表只有一个 返回是回文 
	{
		return true;
	}
	node * a1=head;
	node * a2=head;
	//双指针寻找中点
	while(a2!=NULL  && a2->next!=NULL)//这里考虑了  单数的情况 所以    123454321  会  a1 -> 5     ||||  12345 54321   a1-> 第二个 5  
	{
		a1=a1->next;
		a2=a2->next->next;	
	} 
	a1=reverseList(a1);//翻转中间到后面的代码   
	a2=head;//等于头部代码
	//链表的情况 
	// 1 -> 2-> 3->  4->  5 <-4 <-3<- 2 <-1
	// 1-> 2 -> 3 -> 4 -> 5 ->5 <- 4<- 3 <- 2 <-1
	while(a1!=NULL)//判断是否回文 
	{
		if((a1->i)!=(a2->i))
		{
			return false;
		}
		a1=a1->next;
		a2=a2->next;
	 }
	 return true; 
	
}  



int main()
{
	
	
	//建立  第一个 单链表  
	node *a1=new node;
	node *a2=new node;
	node *a3=new node;
	node *a4=new node;
	node *a5=new node;
	node *a6=new node;
	node *a7=new node;
	node *a8=new node;
	node *a9=new node; 
	
	a1->i=2;//链表节点的复制 
	a2->i=1;
	a3->i=4;
	a4->i=3;
	a5->i=7;
	a6->i=8;
	a7->i=9;
	a8->i=6;
	a9->i=5;
	
	
	a1->next=a2;//链表的连接 
	a2->next=a3;
	a3->next=a4;
	a4->next=a5;
	a5->next=a6;
	a6->next=a7;
	a7->next=a8;
	a8->next=a9;//a5 是 两个链表的节点 
	a9->next=NULL;
	
	//建立  第二个 单链表  
	node *b1=new node;
	node *b2=new node;
	node *b3=new node;
	node *b4=new node;
	node *b5=new node;
	node *b6=new node;
	node *b7=new node;
	node *b8=new node;
	node *b9=new node; 
	
	b1->i=1;//链表节点的复制 
	b2->i=2;
	b3->i=3;
	b4->i=4;
	b5->i=5;
	b6->i=4;
	b7->i=3;
	b8->i=2;
	b9->i=1;
	
	
	b1->next=b2;//链表的连接 
	b2->next=b3;
	b3->next=b4;
	b4->next=b5;
	b5->next=b6;
	b6->next=b7;
	b7->next=b8;
	b8->next=b9;//a5 是 两个链表的节点 
	b9->next=NULL;
	
/*
	int a=fangfa_1(a1);
	if(a==1)
	{
		print(a1); 
		cout<<"这个链表是回文!"<<endl;
	}
	else
	{
		print(a1); 
		cout<<"这个链表不是回文!"<<endl; 
	}
	
	int b=fangfa_1(b1);
	if(b==1)
	{
		print(b1);
		cout<<"这个链表是回文!"<<endl;
	}
	else
	{
		print(b1);
		cout<<"这个链表不是回文!"<<endl; 
	}
	
	
*/	
	int a=fangfa_2(a1);
	if(a==1)
	{
		print(a1); 
		cout<<"这个链表是回文!"<<endl;
	}
	else
	{
		print(a1); 
		cout<<"这个链表不是回文!"<<endl; 
	}
	
	int b=fangfa_2(b1);
	if(b==1)
	{
		print(b1);
		cout<<"这个链表是回文!"<<endl;
	}
	else
	{
		print(b1);
		cout<<"这个链表不是回文!"<<endl; 
	}

	return 	0;
} 

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 21:07:03  更:2022-10-08 21:11:00 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:38:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码