前述:
我将会在此处持续更新我在刷题中遇到的链表类型题目,提交代码均为AC代码,如果有错,感谢您务必指正我。如果有更好的方法,欢迎指教!
面试问答汇总推荐链接:
C++设计模式(23种)汇总及代码实现_芒果甜汤圆的博客-优快云博客
史上最全C/C++面试八股文,一文带你彻底搞懂C/C++面试!_芒果甜汤圆的博客-优快云博客
题目:
JZ6 从尾到头打印链表(从尾到头打印链表_牛客题霸_牛客网 (nowcoder.com))
/*改题目没有给出具体的限制条件,直接顺序遍历链表,
将各个节点的值存储在容器中,然后使用翻转函数反转容器,最后顺序打印容器的值*/
#include <algorithm>
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int>ans;
while(head){
ans.push_back(head->val);
head=head->next;
}
reverse(ans.begin(),ans.end());
return ans;
}
};
JZ24 反转链表(反转链表_牛客题霸_牛客网 (nowcoder.com))
/*
创建一个新结点,然后遍历链表,将各个节点使用头插法插在新节点中实现链表反转
*/
class Solution {
public:
ListNode* ReverseList(ListNode* head) {
if(!head) return nullptr;
ListNode* h=new ListNode(0),*tmp1,*tmp2;
while(head){
tmp1=h->next;
h->next=head;
tmp2=head->next;
head->next=tmp1;
head=tmp2;
}
return h->next;
}
};
JZ25 合并两个排序的链表(合并两个排序的链表_牛客题霸_牛客网 (nowcoder.com))
/*
先判断两个链表中是否存在空链表,如果有则直接返回另一个不为空的链表
同时遍历两个链表,比较两个节点的大小,将小的尾插到新节点(newHead)的尾节点(last)上,
较小的节点更新为它的后续节点,较大的不变继续等待下一次比较。直到有某个链表被遍历完
最后,因为题目没说两个链表等长,所以得判断哪个链表没被遍历完,将其剩余节点直接插入
*/
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
if(!pHead1 || !pHead2) return !pHead1 ?pHead2 : pHead1;
ListNode* newHead=new ListNode(0),*last=newHead;
while(pHead1 && pHead2){
if(pHead1->val > pHead2->val){
last->next=pHead2;
pHead2=pHead2->next;
}else{
last->next=pHead1;
pHead1=pHead1->next;
}
last=last->next;
}
pHead1?last->next=pHead1:last->next=pHead2;
return newHead->next;
}
};
JZ52 两个链表的第一个公共结点(两个链表的第一个公共结点_牛客题霸_牛客网 (nowcoder.com)
/*
这里有一个小技巧就是,如图,红色箭头和绿色箭头走到交汇点的路程是相同的
同时出发,然后到达尾节点后从另一个链表表头再次出发。
具体实现就是利用两个标记,标记是否是第一次到达链表尾部
如果两个出发指针有一个到达了尾部,并且已经有一个已经重新开始过一次,那就说明没有共同节点
另外一种方法就是根据走过的路称来判断是否有公共点
*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
if(!pHead1 || !pHead2) return nullptr;
ListNode* start1=pHead1,*start2=pHead2;
int flag1=0,flag2=0;
while(1){
if(!start1 && !flag1){
start1=pHead2;
flag1=1;
}
if(!start2 && !flag2){
start2=pHead1;
flag2=1;
}
if(start1==start2) return start1;
if(!start1 || !start2 &&flag1) return nullptr;
start1=start1->next;
start2=start2->next;
}
return nullptr;
}
};
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
ListNode *p1=pHead1, *p2=pHead2;
while (p1 != p2){
p1 = p1 ? p1->next : pHead2;
p2 = p2 ? p2->next : pHead1;
}
return p1;
}
};
JZ23 链表中环的入口结点(链表中环的入口结点_牛客题霸_牛客网 (nowcoder.com))
/*
直接遍历链表,因为题目说val的值都大于0,我们将走过的节点的val标记为负数,
在遍历的过程中如果下一个节点的val是负数,那么就说明这个节点为入口,然后要再次遍历一下,把标记的负数还原,然后再返回
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead) {
ListNode* h=pHead;
while(pHead){
if(pHead->next&&pHead->next->val<0){
while(h!=pHead){
if(h->val<0) h->val=-h->val;
h=h->next;
}
pHead->val=-pHead->val;
return pHead->next;
}
pHead->val=-pHead->val;
pHead=pHead->next;
}
return nullptr;
}
};
JZ22 链表中倒数最后k个结点(链表中倒数最后k个结点_牛客题霸_牛客网 (nowcoder.com))
/*
先判断一下长度是不是小于k,小于k返回空
然后再判断一下剩余长度是不是等于总长,等于总长返回头节点
最后遍历一下,通过计数找到对应的节点
*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pHead, int k) {
int len=0;
ListNode* h=pHead;
while(h){
len++;
h=h->next;
}
if(k>len) return nullptr;
if(len==k) return pHead;
h=pHead;
int vis=len-k;
len=0;
while(h){
len++;
if(len==vis) return h->next;
h=h->next;
}
return nullptr;
}
};
JZ35 复杂链表的复制(复杂链表的复制_牛客题霸_牛客网 (nowcoder.com))
/*
先遍历一下,根据顺序创建新的节点,然后将新节点与被创建的旧节点建立对应关系
然后遍历旧节点,看是否有random节点,如果有则通过random节点找到对应的新节点,将其连接
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead) {
if(!pHead) return nullptr;
unordered_map<RandomListNode*,RandomListNode*>mp;
RandomListNode* ans=new RandomListNode(0),*pre=ans,*cur=pHead;
while(cur){
RandomListNode* tmp= new RandomListNode(cur->label);
pre->next=tmp;
mp[cur]=tmp;
pre=pre->next;
cur=cur->next;
}
for(auto& it:mp){
if(it.first->random) it.second->random=mp[it.first->random];
}
return ans->next;
}
};
JZ76 删除链表中重复的结点(删除链表中重复的结点_牛客题霸_牛客网 (nowcoder.com))
/*
这一题我是直接在原有结构上删除了节点,之前看错了题目以为是将有重复的节点删除只剩一个,题目意思是将有重复的节点全部删除。
我个人觉得题目的意思更偏向于直接把原有链表中的节点释放掉,而不是开新的节点
思路:
使用双指针,判断是否有重复的数字,如果有则将快指针在遍历的过程中的重复节点释放掉
然后使用临时变量记录慢指针的位置,慢指针指向快指针,再将临时变量记录的指针释放,直到慢指针指向空
另外一种则是使用队列
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead) {
if(!pHead) return nullptr;
ListNode* ans=new ListNode(0),*cur=pHead,*ne=pHead->next,*aa=ans;
while(cur){
int flag=0;
while(ne && ne->val==cur->val){
flag=1;
ListNode* tmp=ne->next;
delete ne;
ne=tmp;
}
if(flag){
ListNode* tmp=cur;
cur=ne;
delete tmp;
ne=ne->next;
}else{
ListNode* tmp=cur->next;
cur->next=nullptr;
aa->next=cur;
aa=aa->next;
cur=tmp;
ne=cur->next;
}
}
return ans->next;
}
};
JZ18 删除链表的节点(删除链表的节点_牛客题霸_牛客网 (nowcoder.com))
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
ListNode* h=new ListNode(0),*hh=h;
h->next=head;
while(h->next->val!=val) h=h->next;
ListNode* tmp1=h->next,*tmp2=h->next->next;
h->next=tmp2;
delete tmp1;
return hh->next;
}
};