链表常见问题解决思路

链表结点

链表结点声明:

struct ListNode
{
    int value;
    ListNode * next;
    ListNode(int x) : value(x), next(NULL) {}
};

常见链表问题解决思路

1.1 单链表的逆置

  1. 方法一:头插法(迭代法)
    算法思想:逆置链表初始为空,表中节点从原链表中依次“删除”,再逐个插入逆置链表的表头(即“头插”到逆置链表中),使它成为逆置链表的“新”的第一个结点,如此循环,直至原链表为空。
  2. 方法二:递归法:
    算法思想:从后向前改变指向,可以理解成向后的箭头变成了向前的箭头
  3. 方法三:三指针法
    算法思想:从前向后改变指向,可以理解成向后的箭头变成了向前的箭头

1.2 单链表的删除某一节点

  1. 方法一:遍历,
    思路:查找到所要删除的节点,以及其前驱节点,让其前驱节点,指向其后继节点
  2. 方法二:置换法(移花接木)
    思路:明确要删除的节点后,把其后继节点复制到该节点上,然后删除那个后继节点,也等于变相的删除节点(注意如果删除的是尾节点 删除的链表只有一个节点)

1.3 在当前节点前插入一个数据x

  1. 方法一:遍历
    思路:找出当前结点的前驱节点,完成插入;
  2. 方法二:置换法
    思路:把插入节点的数据放到新节点上,把新节点的数据放到插入节点的数据上,这样我们就可以实现在当前节点前插入一个节点了。

1.4 查找链表的中间结点

  1. 快慢指针法
    思路:给一个快指针,让快指针每次移动两步,给一个慢指针,让慢指针每次移动一步,最后结果就是快指针移动到最后一个节点,慢指针最后移动到了中间的节点上。

1.5 单链表的倒数第k个结点

  1. 方法一:正数转换法
    思路:遍历一遍单链表,记录单链表的长度,倒数第k个,即正数length-k+1个,在重头遍历一次便能够找到
  2. 方法二:快慢指针法
    思路:一个指针先走k步,然后两个指针同时走,当先走的那个指针指向空的时候,后面的指针所指即为倒数第K个节点。

1.6 对称单链表

知道链表的长度

  1. 思路:根据对称来确定两个指针的位置,对所指向的元素进行判断,不断前进指针

链表长度未知

  1. 思路1:将前一半的节点压入栈中,并将当前节点继续遍历,每遍历一个都与栈弹出的节点相比较,若不同则不是。
    额外空间复杂度 O(N/2)。
  2. 思路2:不使用辅助空间 两个指针,一个指向头first,指向头的后继节点last;first走一步,last走两步;直到last为空或last的后继节点为空,此时first指向(链表长度为基数,指向中间;为偶数,指向一半);然后fisrt向后走,在申请一个节点指向头,不断进行比较,直到first指向空。

1.7 单链表是否有环

  1. 方法一:map表法
    算法思想:每走一步将走过的节点使用map表存储起来,当遇到第一个在map中存在的节点时,就说明回到了出发点,即链表有环,同时也找到了环的入口。
  2. 方法二:快慢指针法
    算法思想:一个指针走两步;一个指针走一步;如果存在环,两个指针最终会指向同一个元素;如果不存在环,走两步的会最终走向空节点。
  3. 确定有环后求环的长度
    链表常见问题解决思路_第1张图片
    当pSlow和pFast第一次相遇时,pSlow走过的路程为l + a,pFast走过的路程为l + 2*a + c,又因为我们知道pFast的速度为pSlow的两倍,因此可得出l = c;
    此时我们只需要定义一个pMeet指针从头节点出发开始遍历,pSlow从相遇点出发继续遍历,当两个指针相遇时,所指向的节点即为环的入口节点。
    pMeet指针记录环的入口节点,pSlow从入口节点出发向后遍历,当两个指针再次相遇时,pSlow所走过的路径即为环的长度。

1.8 判断两个链表是否相交;相交则求交点(链表不带环)

  1. 思路:
    若两个不带环的链表相交,则他们的尾节点必相同;若要求交点,则需要比较两个链表的长度,让较长的链表先向后遍历至和较短的链表长度相等,然后两个链表同时向后遍历,并比较节点是否相同,当遇到第一个相同的节点时,则为两个链表的交点。

1.9 判断两个链表是否相交,若相交则求交点(链表可能带环)

  1. 情况分析:
    若有两个链表,则他们的带环情况有以下三种可能:
    (1)两个链表都不带环
    直接采用上述思路即可;
    (2)一个链表带环一个链表不带环
    必定不想交;
    (3)两个链表都带环
    下面详细讨论;
  2. 讨论:
    链表常见问题解决思路_第2张图片

当出现①情况时,两个链表不相交。

当出现②情况时,两个链表的交点在环外,那么我们可以转化为不带环链表判断相交即可。

当出现③情况时,两个链表的交点在环内,那么我们可以遍历其中一个链表的环,若在环内与另一个链表环的入口点相交,则两个链表相交,相遇点即为两个链表的交点。

要判断为情况②还是情况③,只需判断两个链表环的入口点是否相同即可。

参考链接:

https://blog.csdn.net/xiangxianghehe/article/details

https://blog.csdn.net/qq_30019237/article/details

https://blog.csdn.net/Dxx_xx4/article/details

你可能感兴趣的:(随记,数据结构)