1.判断单链表是否带环?若带环,求环的长度?求环的入口点?并计算每个算法的时间复杂度&空间复杂度。
int CirculLength( ListNode*crossing)
{
ListNode *cur = crossing;
int count = 1;
while (cur == crossing&&count != 1)
{
cur = cur->next;
}
return count;
}
ListNode* circulEnter(int count; ListNode*plist, ListNode*crossing)
{
ListNode *fast = plist;
ListNode*slow = plist;
while (count--)
{
fast = fast->next;
}
while (fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return *slow;
}
bool iscircul(ListNode*plist)//判断是否带环
{
ListNode*cur = plist;
ListNode*fast = plist;
ListNode*slow = plist;
while (fast)
{
if (fast == slow)
{
int count=CirculLength(fast);
circulEnter(count,plist,fast);
return true;
}
fast=fast->next->next;
slow = slow->next;
}
return false;
}
2.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
ListNode CalCrossing(ListNode l1, ListNode ll2)
{
ListNode0 *l2 = ll2;
while (l1->next)
{
while (l1 != ll2)
1 {
if (l2->next == NULL)
{
l1 = l1->next;
l2 = ll2;
}
ll2 = ll2->next;
}
}
}
bool IsCrossing(ListNode ll1, ListNode ll2)
{
ListNode *ll1 = l1;
ListNode *ll2 = l2;
while (l1)
{
l1 = l1->next;
}
while (l2)
{
l2 = l2->next;
}
if (l1 == l2)
CalCrossing(ll1, ll2);
return true;
else
return false;
}
3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】
bool lv2IsCrossing(ListNode *pl1, ListNode*pl2)
{//1是否带环 (带)在环上相交,在环外相交,(不带)正常
ListNode *p2 = pl2;
ListNode* fast = pl1;
ListNode* slow = pl1;
while (fast->next)
{
fast = fast->next;
slow = slow->next->next;
if (fast == slow)
{
{
ListNode* _fast = pl2;
ListNode* _slow = pl2;
while (_slow->next)
{
_slow = _slow->next;
_fast = _fast->next->next;
if (fast == _fast)
{
CCalPoint(pl1,pl2);
return true;
}
if (_fast == _slow)
{
return false;
}
}
}
}
}
return IsCrossing(pl1, pl2);
}
4.复杂链表的复制。一个链表的每个节点,有一个指向next指针指向下一个节点,还有一个random指针指向这个链表中的一个随机节点或者NULL,现在要求实现复制这个链表,返回复制后的新链表。
//ps: 复杂链表的结构
struct ComplexNode
{
int _data ; // 数据
struct ComplexNode * _next; // 指向下一个节点的指针
struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空)
};
ComplexNode* splitComplexList(ComplexNode * pList);
ComplexNode* BuyComplexNode(int d)
{
ComplexNode* ptr = (ComplexNode*)malloc(sizeof(ComplexNode));
if (ptr == NULL){
perror("malloc");
exit(1);
}
ptr->_data = d;
ptr->_next = NULL;
ptr->_random = NULL;
return ptr;
}
void CopyComplexList(ComplexNode* pList)
{
ComplexNode* tmp = pList;
ComplexNode* newList = pList;
if (pList == NULL || pList->_next == NULL)
return;
//插入节点,在每两个节点之间插入一个节点,数据与前一个相同
while (tmp)
{
ComplexNode* next = pList->_next;
ComplexNode* insert = BuyComplexNode(tmp->_data);
insert->_next = tmp->_next;
tmp->_next = insert;
tmp = insert->_next;
}
//复杂链表的复制
newList = pList;
while (newList)
{
ComplexNode* newcomplexnode = newList->_next;
if (newList->_random != NULL)
{
newcomplexnode->_random = newList->_random->_next;
}
newList = newcomplexnode->_next;
}
}
//链表分离
ComplexNode* splitComplexList(ComplexNode* pList)
{
ComplexNode* tmp = pList;
ComplexNode* list = NULL;
ComplexNode* newlist = NULL;
if (pList != NULL)
{
list = newlist = tmp->_next;
tmp->_next = list->_next;
tmp = tmp->_next;
}
while (tmp)
{
newlist->_next = tmp->_next;
newlist = newlist->_next;
tmp->_next = newlist->_next;
tmp = tmp->_next;
}
return list;
}
ps:为什么单链表会出如此多的面试题,而不是考双向链表的使用呢?
答:因为单链表是一个有缺陷的设计,虽然它的设计有缺陷,但是如果一个程序员面试的时候能将单链表的面试题做出来,不仅考查了面试者的逻辑是否清晰,而且还可以看出面试者的c的学习程度,另外双向链表如果考查的话,考查同样的项目的难度将会减少起码一半,但是能熟练使用单链表的面试者肯定可以轻松的使用双向链表,但是能熟练的使用双向链表的面试者不一定可以熟练地使用单向链表。单链表作为c++的基础,c语言学习的一个学习节点,有着重要的地位,熟练使用链表对于一个程序员的重要程度可想而知。