链表面试题
来源:互联网 发布:福科软件教学 编辑:程序博客网 时间:2024/06/05 08:35
struct node{ int data; node* next;};//打印有序链表的公共部分void fun1(node* l1, node* l2)//假设是升序{ while (l1&&l2)//知道有一个链表的next指向null { if (l1->data > l2->data)//将小值的节点向前移动 l2 = l2->next; if (l1->data < l2->data) l1 = l1->next; if (l1->data == l2->data)//如果值相等,输出然后都向下移 { cout << l1->data; l1 = l1->next; l2 = l2->next; } }}
//删除单链表倒数第K个节点node* fun2(node* l, int k){ if (l == nullptr || k <= 0) return nullptr; node* cur = l; while (l)//遍历链表,对K的情况进行分析 { k--; cur = cur->next; } if (k > 0)//如果K>0,说明没有倒数第K个节点 return l;//,不改变链表,直接返回原链表的头 if (k == 0)//如果K=0, 说明倒数第K个节点就是头结点 l = l->next;//删去头结点,将第二个节点作为头结点 if (k < 0)//当K节点小于零,说明K节点等于零的位置就是要删除节点的迁移个节点 { cur = l; while (++k != 0)//当K=0时,k就停在了n-k的位置 cur = cur->next; cur->next = cur->next->next;//删除第K个节点 } return l;}
//删除双链表倒数第K个节点dnode* fun3(dnode*l, int k){ if (l == nullptr || k <= 0)//若头结点为空或者K小于0,返回空 return l; dnode* cur = l; while (cur)//遍历链表,计算k的情况 { k--; l = l->next; } if (k > 0)//k大于零,说明没有倒数第K个节点 return l; if (k == 0)//等于零,说明倒数第K个节点就是头结点 { l = l->next; l->last = nullptr;//头结点的last指向空 } if (k < 0) { cur = l; while (++k!=0)//当K等于零 cur = cur->next; dnode* newnext = cur->next->next;//删除倒数第K个节点 cur->next = newnext; if (newnext) newnext->last = cur;//将此节点的last指向当前节点 } return l;}
//删除任意n处的节点node* deletenodeab(node*l, int n){ if (n <= 0) return l; if (n == 1) return l; if (n == 2) return l->next;//若只有两个节点,删除第一个节点,返回第二个 if (n > 2) { node* cur = l; while (--n != 1)//向前搜索至删除节点的前个节点 cur = cur->next; cur->next = cur->next->next;//删除节点 } return l;}
//反转单链表node* reverselist(node*l){ node* pnext = nullptr; node* pre = nullptr; while (l) { pnext = l->next;//保存l的下一个节点,防断裂 l->next = pre;//将前一个节点变为当前头结点的下一个节点 pre = l;//将pre(前一个节点)前移 l = pnext;//将头节点前移 } return pre;//返回最新头结点}
//反转双向链表dnode* reversedlist(dnode* l){ dnode* pre = nullptr; dnode*pnext = nullptr; while (l) { pnext = l->next;//保存当前头结点的下一个节点 l->next = pre;//将当前头结点的前一个节点作为下一个节点 l->last = pnext;//将当前节点的后一个节点指向pnext pre = l;//pre节点前移 l = pnext;//头结点前移 } return pre;}
//约瑟夫环问题node* yuesefuhuan(node* l,int m){ if (l == nullptr || l->next == l || m < 1)//头结点为空或者只有一个节点,直接返回 return l; node* last = l; while (last->next != l) last = last->next; int count = 0; while (l != last) { if (++count == m)//如果报数达到m { last->next = l->next;//删除当前节点 count = 0;//计数器重置 } else last = last->next;//否则继续报数 l = last->next; } return l;}
//判断链表是否回文bool ishuiwen(node*l){ stack<node*> temp;//建立辅助栈 node* p = l; while (p)//遍历链表,将链表压栈 { temp.push(p); p = p->next; } while (l) { if (l->data != temp.top()->data)//如果链表节点的值和栈节点的值不等,说明不是回文 return false;//返回FALSE temp.pop();//弹出栈顶元素 l = l->next;//链表前移 } return true;}
//两个单链表相交的一系列问题//问题一:判断链表是否有环,若有,返回第一个环节点node* getloopnode(node* l){ if (l == nullptr || l->next == nullptr || l->next->next == nullptr) return nullptr;//包括头节点在内的前三个节点任意为空,则返回空 node* man = l->next;//慢指针 node* kuai = l->next->next;//快指针 while (kuai != man)//寻找相遇节点 { if (kuai->next == nullptr || kuai->next->next == nullptr) return nullptr; man = man->next;//慢指针走一步 kuai = kuai->next;//快指针走两步 } kuai = l;//相遇之后,快指针重新指向头结点 while (kuai != man)//然后快慢指针都每次走一步,知道相遇,就是入环节点 { kuai = kuai->next; man = man->next; } return man;//返回入环节点}//如何判断两个无环链表是否相交//问题二:如何判断两个无环链表是否相交node* noloop(node* l1, node* l2){ if (l1 == nullptr || l2 == nullptr) return nullptr; node*p1 = l1; node*p2 = l2; int n = 0; while (p1->next)//计算链表1的长度 { ++n; p1 = p1->next; } while (p2->next)//计算链表二的长度 { --n; p2 = p2->next; } if (p1 != p2)//如果尾节点不是同一个节点,必然不相交 return nullptr; p1 = n > 0 ? l1 : l2;//n大于零,说明链表一长度大于链表二 p2 = p1 == l1 ? l2 : l1; n = abs(n);//返回链表一和链表二的公共长度 while (n-- != 0)//长链表先走完多余长度 p1 = p1->next; while (p1 != p2)//寻找公共部分的入口节点 { p1 = p1->next; p2 = p2->next; } return p1;//返回公共部分入口节点}//问题三:判断有环链表是否相交node* doubleloop(node*l1, node*l2, node*loop1, node*loop2){ node* cur1 = nullptr; node* cur2 = nullptr; if (loop1 == loop2)//若入环节点相同,则类似于问题二 { cur1 = l1; cur2 = l2; int n = 0; while (cur1 != loop1)//找到loop1的前一个节点 { ++n;//统计链表1的数目 cur1 = cur1->next; } while (cur2 != loop2)//找loop2的前一个节点 { --n;//判断这两个链表的数目哪个多 cur2 = cur2->next; } cur1 = n > 0 ? l1 : l2;//n大于零,说明链表1长,否则说明链表二长 cur2 = cur1 == l1 ? l2 : l1; n = abs(n);//求取多余节点数目 while (n-- != 0)//走完多余长度 cur1 - cur1->next; while (cur1 != cur2)//寻找公共节点 { cur1 = cur1->next; cur2 = cur2->next; } return cur1; } else { cur1 = loop1->next; while (cur1!=loop1)//遍历环上节点 { if (cur1 == loop2)//若发现了链表二的入环节点,说明有公共部分并返回 return loop1; cur1 = cur1->next; } return nullptr;//否则无公共节点 }}
//合并两个有序单链表node* mergetwo(node* l1, node*l2){ if (l1 == nullptr) return l2; if (l2 == nullptr) return l1; node*p = nullptr; if (l1->data > l2->data)//比较两个链表当前节点值得大小 { p = l2;//若l1大,则把l2作为链表的头结点 p->next = mergetwo(l1, l2->next);//在l1和l2的下一个节点之间继续挑选节点值小的 } if (l1->data < l2->data) { p = l1; p->next = mergetwo(l1->next, l2); } return p;//返回新链表的头结点}
//按照左右半区重新组合单链表void mergelr(node* l, node* r)//合并{ node*next = nullptr; while (l->next) { next = r->next; r->next = l->next; l->next = r; l = r->next; r = next; } l->next = r;}void regroup(node*l)//分离两个链表{ if (l == nullptr || l->next == nullptr) return; node* mid = l, *right = l->next; while (right->next&&right->next->next)//快慢指针查找中间节点 { mid = mid->next; right = right->next->next; } right = mid->next;//将链表分为两个链表 mid->next = nullptr; mergelr(right, l);//重新组合}
//向有序环形单链表中插入新节点node* insertnode(node* l, int num){ node*q = (node*)malloc(sizeof(struct node*));//分配新节点 q->data = num;//对新节点赋值 if (l == nullptr)//若头结点为空,新节点自己组成单循环链表 { q->next = q; return q; } node* p = l->next; while (p!=l)//遍历 { if (p->data <= num&&p->next->data >= num)//发现插入节点的位置 { q->next = p->next;//插入节点 p->next = q; break; } p = p->next; } return l->data > num ? q : l; //因为链表有序,若新节点的值大于头结点,直接返回头结点,若小于,返回新节点(新的头结点)}
//一种怪异的删除节点方式void deletenodewire(node* n){//本质上不是伤处节点,而是将给定节点的下一个节点的值对当前节点进行覆盖,然后删除下一个节点 if (n == nullptr) return; node*p = n->next; n->data = p -> data; n->next = p->next;}
//删除链表中的重复节点(保留重复节点)node* deleterepeatnodes(node*l){ node* cur = l; node*pre = nullptr; node*next = nullptr; while (cur) { pre = cur; next = cur->next; while (next) { if (cur->data == next->data)//发现相邻节点值相等 pre->next = next->next;//删除 else pre = next;//否则依次前进 next = next->next; } cur = cur->next;//当前节点进行一次循环之后,前移一个节点 } return l;}
//删除链表指定值节点node *deletethatnode(node*l, int num){ if (l->next == nullptr || l == nullptr) return l; while (l)//防止头结点就是要删除的节点 { if (l->data != num) break; l = l->next;//重新定义头结点 } node*cur = l; node*pre = l; while (cur) { if (cur->data == num) pre->next = cur->next; else pre = cur; cur = cur->next; } return l;}
//从尾到头打印链表 vector<int> printListFromTailToHead(ListNode* l) { ListNode* p=reverse(l); vector<int> res; while(p) { res.push_back(p->val); p=p->next; } return res; } ListNode* reverse(ListNode* l) { if(l==nullptr||l->next==nullptr) return l; ListNode* pre=nullptr; ListNode* next=nullptr; ListNode* cur=l; while(cur) { next=cur->next; cur->next=pre; pre=cur; cur=next; } return pre; }
0 0
- 常见链表面试题
- 链表面试题
- 常见链表面试题
- 链表面试题小结
- 链表面试题小结
- 链表面试题
- 链表面试题
- 链表面试题
- 常见链表面试题
- 链表面试题集锦
- 链表面试题整理
- 链表面试题
- 链表面试题小结
- 链表面试题小结
- 链表面试题小结
- 单链表面试题
- 链表面试题
- 链表面试题小结
- 游戏API接口开发过程中需要注意哪些事
- hello
- unity总结六
- Android开发学习系列-----开发环境准备
- WPA/WPA2安全认证加密原理详解
- 链表面试题
- android 百分比布局
- 期待!| Kubernetes 1.6 即将发布
- confirm的使用
- maven本地仓库架包存在,项目还是报错?
- JavaScript中声明变量时 带var和不带var的区别
- Protocol Buffer简介
- vc使用speech sdk进行tts语音输出(霜之小刀)
- 经典算法:Dijkstra 算法初探