当前位置:   article > 正文

刷题有术--“链表” 必备技巧_链表笔试技巧

链表笔试技巧

在面试中,链表经常作为简单题出现,虽然题目不难,但是面试者常常会因疏忽实现细节,造成无法短时间内bug-free。

今天小编总结链表常用知识点。点赞收藏,关注公众号[眼罩的程序员笔记],面试前看一遍,快速通关链表题型。

基础操作

01. 快慢指针找中间节点

无论当链表中有奇数还是偶数个节点,slow fast 两指针一开始都指向head。慢指针一次走一步,快指针一次走两步。 直至fast 为NULL或者fast->next为NULL时,此时slow 指向中间节点。

循环结束后指针状态见下图。

  1. ListNode * findMiddle(ListNode * head)
  2. {
  3.    ListNode * slow = head;
  4.    ListNode * fast = head;
  5.    while(fast!=NULL && fast->next!=NULL)
  6.    {
  7.       slow = slow->next;
  8.       fast = fast->next->next;
  9.    }
  10.    return slow;
  11. }

02. 原地翻转

不断向后移动相邻的两个指针,翻转两指针间的相邻关系,需注意在翻转之前保存后一个指针的next节点。并且最后把原head的next置为NULL。

如下图红色代表循环第一步,蓝色代表循环第二步。

  1. ListNode * reverse(ListNode * head)
  2.  {
  3.     if (head==NULL)
  4.       return NULL;
  5.     ListNode * i = head;
  6.     ListNode * j = head->next;
  7.     while(j!=NULL)
  8.     {
  9.        ListNode * tem = j->next;
  10.        j->next = i;
  11.        i= j;
  12.        j=tem;
  13.     }
  14.     head->next = NULL;
  15.     return i;
  16.  }

03. 合并链表

给定两个链表,要求依次选取其中一个节点,合并两个链表。

下图是一个通用的合并思路,这个思路不仅适用于依次选取节点合并,还适用于将两个有序链表合并为一个有序链表。

首先建立一个dummy 头节点作为合并后链表的dummy头结点,用一个尾指针指向合并后链表的最后一个节点。每次循环将tail 连接到headA,headA 连接到 headB,之后tail 更新为headB。

下图中红线代表循环第一轮,蓝线代表循环第二轮。

  1. ListNode * merge(ListNode * a, ListNode * b)
  2. {
  3.    ListNode * dummy = new ListNode(-1);
  4.    ListNode * pre = dummy;
  5.    while(a!=NULL && b!=NULL)
  6.    {
  7.       pre->next = a;
  8.       ListNode * aTem = a->next;
  9.       a->next = b;
  10.       pre=b;
  11.       b=b->next;
  12.       a=aTem;
  13.    }
  14.    if(a!=NULL)
  15.    {
  16.       pre->next= a;
  17.    }
  18.    else if (b!=NULL)
  19.    {
  20.       pre->next =b;
  21.    }
  22.    return dummy->next;
  23. }

链表排序

题目:给定链表的头结点 head ,请将其按升序排列并返回 排序后的链表 。

链表的特点造成无法方便的交换任意两个任意位置的节点,所以无法使用快排类的排序算法。

而归并排序非常适合链表排序。递归从底到上,相当将长度为1 的子链表排序之后两个合并成长度2的链表;依次递推。

实现过程就用到了上述基础操作中的「快慢指针找中间节点」来把链表一分为二;用「合并链表」将排序好的子链表合并成一个有序的长链表。

链表有环

1. 给你一个链表的头节点 head ,判断链表中是否有环?

这个题比较简单就是使用快慢指针,慢指针一次走一步,快指针一次走两步,如果快指针在走到结尾之前和慢指针相遇了说明有环,如果没相遇则无环。

2. 如果链表有环,则返回环的起点。

这是上题的follow up, 先明确符号含义:

x: 头结点到 entry红点之间的长度;

y: entry 红点到 meet 红点之间的长度;

m:meet红点 到 entry 红点之间的长度;

R:环的整个长度;

t:  t时刻快慢指针在meet点相遇。

假设快慢指针在环内的meet点相遇。

快指针走的距离是慢指针走的距离的两倍,有如下两个等式:

2t = x + n* R + y(快指针);

  t  = x + y         (慢指针)

通过这两个等式可以得到 x = n*R - y;   推出 x = m + (n-1)*R。说明相遇之后将慢指针重新放回起点,快指针后面一次只走一步,两个指针再次相遇的点即为entry 入口点。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/523660
推荐阅读
相关标签
  

闽ICP备14008679号