左神基础班-单链表存储的数,判断回文

博客介绍了链表回文判断的解法,给出时间和空间复杂度均为O(n)的解法,说明了其中几个函数的功能,还贴出时间复杂度为O(n)、空间复杂度为O(1)的代码,并提到设立help指针辅助修改节点指针,强调回文数时要修正链表指针。

先上时间复杂度和空间复杂度 都是 O(n)的解法

 

里面的几个函数功能分别为:1.由数组生成链表、2.得到反转后的链表、3.顺序打印链表,4.比较两个链表,若有一处不同,则不是回文。

#include<iostream>
#include<stack>
using namespace std;
struct LinkNode{
	int value;
	LinkNode* next;
};
LinkNode* getLink(int arr[], int length);
LinkNode* getLink_reverse(LinkNode* head1, int length);
void show(LinkNode* head);
bool compare(LinkNode* head1, LinkNode* head2);

int main(){
	int arr1[] = {1,2,3,2,1};
	LinkNode* head1 = getLink(arr1,5);
	LinkNode* head2 = getLink_reverse(head1, 5);
	// show(head1);
	// show(head2);
	cout << "is huiwen: "<< compare(head1, head2);
	return 0;
}

LinkNode* getLink(int arr[], int length){
	LinkNode* head = new LinkNode();
	LinkNode* go = head;
	int i =0;
	while(i<length){
		LinkNode* node = new LinkNode();
		node->value = arr[i];
		node->next = nullptr;
		go->next = node;
		go = go->next;
		i++;
	}
	return head;	
}
LinkNode* getLink_reverse(LinkNode* head1 , int length){
	stack<int> s;
	LinkNode* go = head1->next;
	while(go!=nullptr){
		s.push(go->value);
		go=go->next;
	}
	LinkNode* head2 = new LinkNode();
	LinkNode* go2 = head2;
	while(!s.empty()){
		LinkNode* node = new LinkNode();
		node->value = s.top();
		s.pop();
		node->next = nullptr;
		go2->next = node;
		go2 = go2->next;
	}
	return head2;
}
void show(LinkNode* head){
	LinkNode* go = head->next;
	while(go!=nullptr){
		cout << go->value << endl;
		go = go->next;
	}
}
bool compare(LinkNode* head1, LinkNode* head2){
	LinkNode* go1 = head1->next;
	LinkNode* go2 = head2->next;
	while((go1!= nullptr && go2 != nullptr) &&
			 go1->value == go2->value){
		go1 = go1->next;
		go2 = go2->next;
	}
	return go1==nullptr? true : false;
}

+————————————————————————————————————————————————————————+

 

下面贴时间复杂度位O(n),空间复杂度为O(1)的代码

 

#include<iostream>
#include<stack>
using namespace std;
struct LinkNode{
	int value;
	LinkNode* next;
};
LinkNode* getLink(int arr[], int length);
void show(LinkNode* head);
bool judge(LinkNode* head);
int main(){
	int arr1[] = {1,2,3,3,2,1};
	LinkNode* head1 = getLink(arr1,6);
	// show(head1);
	cout << "is huiwen: " << judge(head1)<<endl;
	return 0;
}

LinkNode* getLink(int arr[], int length){
	LinkNode* head = new LinkNode();
	LinkNode* go = head;
	int i =0;
	while(i<length){
		LinkNode* node = new LinkNode();
		node->value = arr[i];
		node->next = nullptr;
		go->next = node;
		go = go->next;
		i++;
	}
	return head;	
}
void show(LinkNode* head){
	LinkNode* go = head->next;
	while(go!=nullptr){
		cout << go->value << endl;
		go = go->next;
	}
}

bool judge(LinkNode* head){
	LinkNode* slow;
	LinkNode* fast;
	slow = fast = head->next;
	while(fast->next != nullptr && fast->next->next != nullptr){
		slow = slow->next;
		fast = fast->next->next;
	}
	//此时,slow指向中间的节点
	fast = slow->next;
	slow->next = nullptr;
	LinkNode* help = fast->next;
	while(help != nullptr){
		fast->next = slow;
		slow = fast;
		fast = help;
		help = help->next;	
	}
	fast->next = slow;
	//反转指针完毕,判断回文情况
	LinkNode* front = head->next;
	LinkNode* tail = fast;
	while(front !=nullptr ){
		if(front->value != tail->value){
			return false;
		}
		// cout << "now ,front is:" << front->value <<" tail is: "<< tail->value << endl;
		front = front->next;
		tail = tail->next;
	}
	//把指针调整回去
	slow = fast;
	fast = fast->next;
	slow->next = nullptr;
	help = fast->next;
	while(help != nullptr){
		fast->next = slow;
		slow = fast;
		fast = help;
		help = help->next;
	}
	fast->next = slow;
	return true;

}

 

来个图片帮助理解。

 

 

其中,要设立一个help指针。其指向正在被改变指针节点 的那个节点的下一个节点。

这样,当一个节点其后指针改变时。还能找到其原先的后一个节点,方能继续修改。

 

记得如果是回文数的话要把 链表中的指针修正回来哦?+~

单链表判断回文主要有以下两种常见方法: ### 方法一:将链表据拷贝到组中进行判断 该方法的思路是先获取单链表的长度,然后将链表中的据依次拷贝到一个动态分配的组中,最后通过双指针法从组两端向中间遍历,比较对应位置的元素是否相等。若在遍历过程中发现不相等的元素,则链表不是回文;若遍历完都相等,则链表是回文。 以下是对应的代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <assert.h> // 假设 ELEM_TYPE 为 int 类型 typedef int ELEM_TYPE; // 定义链表节点结构体 typedef struct Node { ELEM_TYPE data; struct Node* next; } Node, *PNode; // 获取链表长度的函 int Get_length(PNode plist) { int len = 0; PNode p = plist; while (p != NULL) { len++; p = p->next; } return len; } // 判断单链表是否回文 bool IsPail(PNode plist) { // 需要两个指针,一个指向头,一个指向尾,一个向后走,一个向前走,判断据是否相等 // 单链表无法从后节点指向前节点,因此将单链表据拷贝到组中进行判断 int len = Get_length(plist); ELEM_TYPE* tmp = (ELEM_TYPE*)malloc(len * sizeof(ELEM_TYPE)); assert(tmp != NULL); int i = 0; for (PNode p = plist; p != NULL; p = p->next) { tmp[i++] = p->data; } int left = 0; int right = len - 1; while (left < right) { if (tmp[left] != tmp[right]) { free(tmp); return false; } left++; right--; } free(tmp); return true; } ``` ### 方法二:修改链表结构让后半段可反向遍历 此方法不创建新链表,而是在原链表基础上进行操作。由于单链表无法直接从后向前遍历,所以需要对链表进行修改,使后半段链表可以反向遍历。具体步骤可能包括找到链表的中间节点,然后反转后半段链表,最后比较前半段和反转后的后半段链表的元素是否相等。若都相等,则链表是回文;否则不是回文
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值