🙂找中间节点一定要考虑偶数个和奇数个的问题。
🙂指针指向的前中后。
🙂链表节点的位置个数/链表的节点中的数字。🆗🆗
今天最后两道链表OJ题目。
10.链表的回文结构
描述
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
【快慢指针中间节点+逆置链表+比较链表】
- 先找到链表的中间节点(分奇偶)
- 逆置后半段链表
- 两个指针比较两个链表
- 结束条件,某个指正为NULL就结束
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) {} };*/ class PalindromeList { public: bool chkPalindrome(ListNode* A) { //找中间节点 ListNode*slow=A; ListNode*fast=A; while(fast->next && fast) { fast=fast->next->next; slow=slow->next; } //逆置后半段链表 ListNode*head=slow; ListNode*rhead=NULL; ListNode*cur=head; ListNode*tail=NULL; while(cur) { ListNode*tmp=cur->next; if(rhead == NULL) { rhead=tail=cur; rhead->next=NULL; } else { rhead=cur; rhead->next=tail; tail=rhead; } cur=tmp; } //比较rhead while(rhead && A) { if(rhead->val != A->val) { return false; } rhead=rhead->next; A=A->next; } return true; } };
11.随机链表的复制(链表的深度拷贝)
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
- val:一个表示 Node.val 的整数。
- random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
你的代码 只 接受原链表的头节点 head 作为传入参数。
示例一:
示例二:
【 尾插+某个位置插入】
- 这道题目的综合性还挺强的,大家一定要把前面链表的知识扎根。才能轻易上手。
- 单链表+随机链表(随机链表可以指向其他任何链表包括自己)
- 不要一个指针搞定所有,大概率是会出错❌
- 画图细致比较重要
/** * Definition for a Node. * struct Node { * int val; * struct Node *next; * struct Node *random; * }; */ struct Node* copyRandomList(struct Node* head) { //第一步 struct Node* cur=head; while(cur) { struct Node*copy=(struct Node*)malloc(sizeof(struct Node)); copy->val=cur->val; copy->next=cur->next; cur->next=copy; cur=cur->next->next; //cur=copy->next; } //第二步 cur=head; while(cur) { struct Node*copy=cur->next; if(cur->random == NULL) { copy->random=NULL; } else { copy->random=cur->random->next;//易错 } cur=copy->next; //cur=cur->next->next; } //第三步 cur=head; struct Node*newhead=NULL; struct Node*tail=NULL; while(cur) { struct Node*copy=cur->next; if(newhead == NULL) { newhead=tail=copy; } else { tail->next=copy; tail=tail->next; } cur->next=copy->next; cur=copy->next; } //最后一个节点本来就指向NULL return newhead; }
【找具体位置第几个】
但是这个方法的时间复杂度是O(N^2),时间复杂度是非常高的,建议学会上面的方法。
12.链表逆置(头插)和链表顺序(尾插)
【头插】
struct ListNode* reverseList(struct ListNode* head) { struct ListNode*newhead=NULL; struct ListNode*cur=head; while(cur) { struct ListNode*tmp=cur->next; cur->next=newhead; newhead=cur; cur=tmp; } return newhead; }
【尾插】
struct ListNode* removeElements(struct ListNode* head, int val) { struct ListNode* cur=head; struct ListNode* tail=NULL; struct ListNode* newhead=NULL; while(cur) { if(cur->val != val) { if(tail) { tail->next=cur;//易错 tail=tail->next; } //处理头 else { newhead=tail=cur;//易错 } cur=cur->next; } else { struct ListNode* tmp=cur->next; free(cur); cur=tmp; } } //处理尾 if(tail) { tail->next=NULL; } return newhead; }
最近天气渐冷,大家要注意保暖哦。
代码---------→【唐棣棣 (TSQXG) - Gitee.com】
联系---------→【邮箱:2784139418@qq.com】