您的位置:首页 > 其它

链表常见题总结一

2016-08-09 21:51 204 查看
     链表可以说是笔试面试的重点,因为写一个链表相关的题可以在短时间写出来,并且考验测试人的水平。特别将平时经常做的链表的题拿上来,做个小结。

   1. 求单链表中结点的个数

   2. 将单链表反转

   3. 查找单链表中的倒数第K个结点(k > 0)

   4. 查找单链表的中间结点

   5. 已知两个单链表pHead1 和pHead2 各自有序,把它们合并成一个链表依然有序

   6. 判断一个单链表中是否有环

   7. 判断两个单链表是否相交

  8. 求两个单链表相交的第一个节点

  9. 已知一个单链表中存在环,求进入环中的第一个节点

  10. 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted

  1.求单链表节点的个数

//求单链表中结点的个数
int Length(ListNode *phead)
{
int len = 0;
while (phead != NULL)
{
len++;
phead = phead->pnext;
}
return len;
}

   2.单链表反转

     我是按照递归和非递归做的
     
//单链表反转
ListNode* Reverse(ListNode *phead)
{
if (phead == NULL||phead->pnext==NULL)
return phead;
ListNode *pre = new ListNode(0);
ListNode *temp = pre;
pre->pnext = phead;
ListNode* cur = phead;
ListNode* next = phead->pnext;
while (next != NULL)
{
cur->pnext = pre;
pre = cur;
cur = next;
next = next->pnext;
}
cur->pnext = pre;
phead->pnext = NULL;
delete temp;
return cur;
}

//单链表反转,递归
ListNode* ReverseRecursion(ListNode* phead)
{
if (phead == NULL || phead->pnext == NULL)
return phead;
ListNode *temp = phead->pnext;
ListNode *newhead=ReverseRecursion(temp);   //先反转链表结点的后一个结点
temp->pnext = phead;            //将该结点放在其原来后面结点的后一个结点
phead->pnext = NULL;
return newhead;
}

    3.倒数第K个节点

//查找单链表中的倒数第K个结点(K>0),采用双指针法
ListNode* TheKthListNode(ListNode* phead,int k)
{
ListNode *fast = phead;
int i = 0;
while (i < k-1 && fast != NULL)
{
fast = fast->pnext;
i++;
}
if (fast == NULL)
return NULL;
ListNode *slow = phead;
while (fast->pnext != NULL)
{
slow = slow->pnext;
fast = fast->pnext;
}
slow->pnext = NULL;
return slow;
}

    4.查找单链表的中间节点

//找出单链表的中间结点,采用快慢指针
ListNode* MiddleNode(ListNode* phead)
{
ListNode *slow = phead;
ListNode *fast = phead;
if (phead == NULL)
return phead;
while (fast->pnext != NULL)
{
fast = fast->pnext;
slow = slow->pnext;
if (fast->pnext != NULL)
fast = fast->pnext;
}
return slow;
}

     5.合并两个有序的链表,使得结果仍然有序

//两链表各自有序,合并成一个链表依然有序
ListNode* Merge(ListNode *phead1, ListNode *phead2)
{
if (phead1 == NULL)
return phead1;
if (phead2 == NULL)
return phead2;
ListNode *pre=new ListNode(0);
ListNode *cur = pre;
ListNode *temp = NULL;
while (phead1 && phead2)
{
temp = phead1->val < phead2->val ? phead1 : phead2;
cur->pnext = temp;
cur = temp;
if (temp == phead1)
phead1 = phead1->pnext;
else
phead2 = phead2->pnext;
}
while (phead1)
{
cur->pnext = phead1;
cur = cur->pnext;
phead1 = phead1->pnext;
}
while (phead2)
{
cur->pnext = phead2;
cur = cur->pnext;
phead2 = phead2->pnext;
}
cur->pnext = NULL;
temp = pre->pnext;
delete pre;
return temp;
}

     6.判断单链表是否有环

//判断一个单链表是否有环,同样采用快慢指针,要是他们重合就有环
bool IsCircle(ListNode *phead)
{

ListNode *fast = phead;
ListNode *slow = phead;
while (fast!=NULL && fast->pnext!=NULL)
{
fast = fast->pnext->pnext;
slow = slow->pnext;
if (fast == slow)
return true;
}
return false;
}

     7.判断两个单链表是否相交

//判断两个单链表是否相交,若相交,则两个链表的最后一个节点必定相同,否则不相交
bool IsConnect(ListNode *phead1, ListNode *phead2)
{
if (phead1 == NULL || phead2 == NULL)
{
return false;
}
while (phead1->pnext != NULL)
{
phead1 = phead1->pnext;
}
while (phead2->pnext != NULL)
{
phead2 = phead2->pnext;
}
if (phead1 == phead2)
return true;
else
return false;
}

     8.求两个链表相交的第一个节点

//求两个单链表相交的第一个节点,先分别计算两个链表的长度,再让长的链表先走超出的那部分,然后两个链表步调相同
ListNode* TheFirstConnectNode(ListNode *phead1, ListNode *phead2)
{
if (phead1 == NULL || phead2 == NULL)
{
return NULL;
}
ListNode *temp1 = phead1;
ListNode *temp2 = phead2;
int len1 = 0, len2 = 0;
while (temp1->pnext != NULL)
{
len1++;
temp1 = temp1->pnext;
}
while (temp2->pnext != NULL)
{
len2++;
temp2 = temp2->pnext;
}
if (temp1 != temp2)
return NULL;
else
{
if (len1 > len2)
{
temp1 = phead1;
for (int i = 0; i < len1 - len2;i++)
{
temp1 = temp1->pnext;
}
temp2 = phead2;
}
else
{
temp2 = phead2;
for (int i = 0; i < len2 - len1; i++)
{
temp2 = temp2->pnext;
}
temp1 = phead1;
}
while (temp1 != temp2)
{
temp1 = temp1->pnext;
temp2 = temp2->pnext;
}
return temp1;
}
}

     9.已知单链表有环,求进入环中的第一个节点

//已知单链表有环,求进入环中的第一个节点
ListNode *TheFirstCircleNode(ListNode *phead)
{
//先找一个在环中的节点,采用快慢指针
ListNode *fast = phead->pnext->pnext;
ListNode *slow = phead->pnext;
while (fast != slow)
{
slow = slow->pnext;
fast = fast->pnext->pnext;
}
//计算环的长度
int len = 1;
fast = fast->pnext;
while (fast!=slow)
{
len++;
fast = fast->pnext;
}
//让一个快指针先走len,然后慢指针开始走,当两个第一次相遇点就是环的第一个节点
fast = phead;
slow = phead;
for (int i = 0; i < len; i++)
{
fast = fast->pnext;
}
while (fast != slow)
{
fast = fast->pnext;
slow = slow->pnext;
}
slow->pnext = NULL; //此处只是为了提炼一个节点出来,免得打印的时候因为是循环,打印循环输出一满屏
return slow;
}

    10.删除一个指定节点,时间复杂度为O(1)

//给出一单链表头指针和一节点指针toBeDel,O(1)时间复杂度删除节点toBeDel
void DelOneNode(ListNode *phead, ListNode *toBeDel)
{
if (toBeDel->pnext == NULL)
{
toBeDel = NULL;
}
toBeDel->val = toBeDel->pnext->val;      //O(1)时间复杂度的话只能将后面节点的值赋给该结点,在将
toBeDel->pnext = toBeDel->pnext->pnext;  //要删除的节点的后一个节点删除;
}


文中均为自己写的代码,均通过自己写的简单的测试,但是肯定还有些测试不能通过,希望有人找出错误给我纠正一下,不胜感谢。待更新ing..
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: