链表的回文结构
记录我第一次独立写出来一道困难题,技巧是慢慢积累出来的,我不是那种很聪明的人,但我一定不能做一个懒的人。
链表的回文结构
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
我的大致思路是这样的:首先将这个链表A进行深拷贝一份,拷贝为链表B,然后将链表B进行翻转,然后A与B再进行逐个进行比较。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
// write code here
if (A == NULL)
return false;
if (A->next == NULL)
return true;
struct ListNode* pa = A;
//将链表A深拷贝一份
struct ListNode* B = deepCopy(A);
//翻转
B = reverseList(B);
//翻转之后prev指向最后
//逐步和A进行比较
struct ListNode* pb = B;
pa = A;
while (pa) {
if (pa->val != pb->val)
return false;
pa = pa->next;
pb = pb->next;
}
return true;
}
public:
//翻转链表
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* prev = NULL;
struct ListNode* curr = head;
while (curr) {
struct ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
public:
struct ListNode* deepCopy(struct ListNode* A)
{
struct ListNode* pa = A;
struct ListNode* B = (struct ListNode*)malloc(sizeof(struct ListNode));
B->val = pa->val;
B->next = NULL;
pa = pa->next;
struct ListNode* pb = B;
while (pa)
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = pa->val;
pb->next = newnode;
pb = pb->next;
pb->next = NULL;
pa = pa->next;
}
return B;
}
};
链表的深拷贝
所谓深拷贝就是搞一个备份,这个备份和原来的结构相同,关系相同,是在同一个时间下另一个空间的存在。
struct ListNode* deepCopy(struct ListNode* A)
{
struct ListNode* pa = A;
struct ListNode* B = (struct ListNode*)malloc(sizeof(struct ListNode));
B->val = pa->val;
B->next = NULL;
pa = pa->next;
struct ListNode* pb = B;
while (pa)
{
struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
newnode->val = pa->val;
pb->next = newnode;
pb = pb->next;
pb->next = NULL;
pa = pa->next;
}
return B;
}
有关链表的深拷贝这个问题,leetcode上有相关的题目,以后如果再遇到了,我还会写在这里。
138.复制带随机指针的链表
![[Pasted image 20221108101753.png]]
这道题的难点在于怎么进行random指针的深拷贝,因为这个随机指针的指向毫无规律,所以由此我们就能想到让这个毫无规律变成有迹可循,我们首先在每一个节点后面先接上一个他们自身的拷贝,这样就可以在另一个空间上有一个复制体,但是只是这样还不够,我们发现,新节点的随机指针就应该指向旧结点随机指针指向的后一个结点,好了,随机指针的问题解决了,我们接下来要做的就是让新节点指向它的next的next这样新链表也就构建好了。
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head) {
if (head == NULL) {
return NULL;
}
struct Node* cur=head;
while(cur)
{
struct Node* newnode=(struct Node*)malloc(sizeof(struct Node));
newnode->val=cur->val;
newnode->next=cur->next;
cur->next=newnode;
cur=newnode->next;
}
cur=head;
while(cur)
{
if(cur->random==NULL)
{
cur->next->random=NULL;
cur=cur->next->next;
}
else
{
cur->next->random=cur->random->next;
cur=cur->next->next;
}
}
cur=head->next;
while(cur)
{
if(cur->next!=NULL)
{
cur->next=cur->next->next;
cur=cur->next;
}
else
{
cur->next=NULL;
cur=cur->next;
}
}
return head->next;
}
链表的翻转
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* prev=NULL;
struct ListNode* curr=head;
while(curr)
{
struct ListNode* next=curr->next;
curr->next=prev;
prev=curr;
curr=next;
}
return prev;
}