单链表常见笔试面试题总结
2017-07-18 17:57
651 查看
1.单链表逆置
2.逆序打印单链表
3.给定单链表,检测是否有环
思想:使用快慢指针,快指针每次走两格,慢指针每次走一格。如果有环,快慢指针总会相遇。如果快慢指针相遇,说明有环。如果快指针为NULL,则说明无环。
4.求环的长度
思想:从相遇节点开始,下次再走到该相遇点时经过的节点数为环的长度。
5.给定单链表(head),如果有环的话返回从头结点进入环的第一个节点
思想:有定理证明,碰撞点到尾节点的距离=头节点到入口点的距离。慢指针从头节点开始走,快从相遇点开始走。当快指针为NULL时,慢指针所指的节点为环的第一个节点。
6.给定两个单链表(plist1, plist2),检测两个链表是否有交点,如果有返回第一个交点
思想:如果plist1==plist2,链表相交点就是plist1。否则,先求出链表的长度,让快指针先走len1-len2步,然后快慢指针开始走,每次走一步。当快指针走到尾节点时,慢指针指向的节点为链表的相交点。
7.只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点
思想:用后值覆盖前值,删除最后一个节点。切记:将倒数第二个节点的next域置为NULL。
8.给定单链表头结点,删除链表中倒数第k个结点
思想:快指针先走K步,然后快慢指针一块走,每次走1步,当快指针到达结尾的下一个节点(NULL)时,慢指针到达倒数第K个节点
9.只给定单链表中某个结点p(非空结点),在p前面插入一个结点val
思想:在p后面添加一个节点s,s->value=p->value; p->value=val
#include <iostream> using namespace std; typedef int KeyType; typedef struct Node { KeyType value; Node *next; }Node, *List; void Reserver(List plist) { // 链表为NULL/只有一个头节点/链表只有一个头节点和数据节点 --->不用交换 if(plist==NULL|| plist->next==NULL|| plist->next->next==NULL) { return; } //链表至少有两个节点 Node *p = plist->next; Node *q = p->next; Node *s; plist->next = NULL;//头节点要指向尾节点,先将其指针域赋为NULL while(q != NULL) { s = q->next; q->next = p; p = q; q = s; } plist->next = p; return; }
2.逆序打印单链表
//1.如果要破坏单链表的结构,则像1题一样,使用断链-接链,然后遍历单链表 //2.如果不能破坏单链表的结构,可以使用stack,遍历后压栈,最后统一出栈 #include <iostream> #include <stack> using namespace std; void PrintReserve(List plist) { if(plist == NULL) return; stack<KeyType> st; Node *p = plist->next; while(p != NULL) { st.push(p->value); p = p->next; } while(!st.empty()) { cout<<st.top()<<endl; st.pop(); } return; }
3.给定单链表,检测是否有环
思想:使用快慢指针,快指针每次走两格,慢指针每次走一格。如果有环,快慢指针总会相遇。如果快慢指针相遇,说明有环。如果快指针为NULL,则说明无环。
bool IsExitLoop(List plist) { if(plist==NULL || plist->next==NULL) { return false; } Node *fast = plist; Node *slow = plist; while(fast!=NULL || slow!=NULL) { slow = slow->next; fast = fast->next->next; if(slow == fast) { break; } } //退出循环,slow==false,有环 或者fast==NULL,没有环 return fast==NULL ? false : true; }
4.求环的长度
思想:从相遇节点开始,下次再走到该相遇点时经过的节点数为环的长度。
int LoopLength(List plist) { if(plist==NULL || plist->next==NULL) return 0; Node *fast = plist; Node *slow = plist; while(fast!=NULL || slow!=NULL) { slow = slow->next; fast = fast->next->next; if(slow == fast) { break; } } if(fast == NULL)//没有环 { return 0; } Node *tmp = slow; slow = slow->next; int count = 1; while(slow != tmp) { slow = slow->next; ++count; } count += 1; return count; }
5.给定单链表(head),如果有环的话返回从头结点进入环的第一个节点
思想:有定理证明,碰撞点到尾节点的距离=头节点到入口点的距离。慢指针从头节点开始走,快从相遇点开始走。当快指针为NULL时,慢指针所指的节点为环的第一个节点。
Node *FindEntryNode(List plist) { if(plist==NULL || plist->next==NULL) return NULL; Node *fast = plist; Node *slow = plist; while(fast!=NULL || slow!=NULL) { slow = slow->next; fast = fast->next->next; if(slow == fast) { break; } } if(fast ==NULL) { return NULL; } slow = plist; while(fast != slow) { fast = fast->next; slow = slow->next; } return slow==fast ? slow : NULL; }
6.给定两个单链表(plist1, plist2),检测两个链表是否有交点,如果有返回第一个交点
思想:如果plist1==plist2,链表相交点就是plist1。否则,先求出链表的长度,让快指针先走len1-len2步,然后快慢指针开始走,每次走一步。当快指针走到尾节点时,慢指针指向的节点为链表的相交点。
Node *FindNode(List plist1, List plist2) { if(plist1==NULL || plist2==NULL)//指针不为NULL { return NULL; } if(plist1 == plist2)//指针指向同一个链表 { return plist1; } Node *p = plist1; Node *q = plist2; int len1 = 0; int len2 = 0; for(; p!=NULL; p=p->next) ++len1; for(; q!=NULL; q=q->next) ++len2; int num = len1>len2 ? len1-len2 : len2-len1; int i =0; p = plist1; while(i<num && p->next!=NULL) { p = p->next; ++i; } q = plist2->next; while(p != q) { p = p->next; q = q->next; } return q; }
7.只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点
思想:用后值覆盖前值,删除最后一个节点。切记:将倒数第二个节点的next域置为NULL。
bool DeleteNode(Node *p) { if(p == NULL) return false; Node *tmp; while(p->next != NULL) { p->value = p->next->value; if(p->next->next == NULL) { tmp = p; } p = p->next; } tmp->next = NULL; delete p; return true; }
8.给定单链表头结点,删除链表中倒数第k个结点
思想:快指针先走K步,然后快慢指针一块走,每次走1步,当快指针到达结尾的下一个节点(NULL)时,慢指针到达倒数第K个节点
bool DeleteKNode(List plist, int num) { if(plist==NULL || plist->next==NULL || num<1) return false; Node *front = plist; for(int i=0; i<num; ++i) { if(front ==NULL) return false; front = front->next; } Node *back = plist; Node *tmp = plist; while(front != NULL) { front = front->next; back = back->next; } //back所指向的节点为倒数第K个节点 DeleteNode(back); return true; }
9.只给定单链表中某个结点p(非空结点),在p前面插入一个结点val
思想:在p后面添加一个节点s,s->value=p->value; p->value=val
bool InsertNode(Node *p, KeyType val) { Node *s = (Node *)malloc(sizeof(Node)); s->next = p->next; p->next = s; s->value = p->value; p->value = val; return true; }
相关文章推荐
- 【数据结构】链表的原理及与其相关的常见面试题总结
- 计算机组成常见笔试、面试题总结
- 常见笔试面试题:实现一个递增排序的单链表
- 【不定期更新】FPGA/IC岗位常见笔试面试题总结
- 嵌入式软件常见笔试面试题总结
- 数据库常见笔试、面试题总结
- 【数据结构】链表的原理及与其相关的常见面试题总结
- 嵌入式软件常见笔试面试题总结
- 常见链表面试题的总结
- 链表的一些常见笔试面试问题总结及代码
- 嵌入式软件常见笔试面试题总结 .
- 单向链表常见的笔试面试题
- 常见算法笔试或面试题
- 常见java面试题总结
- 链表笔试面试题
- java常见面试题总结
- iOS常见面试题总结
- 常见算法笔试或面试题
- 二叉树类型笔试面试题大总结(含代码)
- C语言实现单链表常见面试题