剑指Offer分类——链表(6,24,22,23,25,35,52,18)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lollipop66/article/details/80958898

链表:我觉得链表在做题的时候一个很好的方法就是画图,通过画图将指针不断变化,这样可以很好的将指针指来指去!!!


6. 从尾到头打印链表

思路1(不改变链表结构):从尾到头打印链表,我们知道链表是一个只能向后不能向前的结构(单链表),那我们想从后向前打印,就可以想到一个结构叫做栈,栈结构是后进先出,也就是说,我们可以让链表的每一个元素一次进栈,然后出栈的时候就是从链表的末尾先出栈,

所以我们可以采用栈结构对其进行存储;

思路2(改变链表结构):对链表进行反转,也就是说将链表的尾变成链表的头(下一题有思路)


24. 反转链表

思路:我们需要对链表进行反转,那么我们就不能让链表的链断了,换句话说,就是不能找不到链表的下一个节点,所以我们可以使用单个指针对链表的单个点进行存储,

一个是当前节点current(就是需要将这个节点连接到前面的结点上),

一个是当前节点的前一个节点pre(因为我们需要把current连接到pre上,把current作为pre 的一个节点),

一个是current的下一个节点cNext(就是下一个需要连接到current后面的结点),

整个过程不断更新,得到整个链表的反转链表


22.链表中倒数第k个节点

思路:单链表是一个顺序不可逆的结构,我们想得到倒数第k个节点,可以使用一个count记录进入了多少个节点,通过记录当前节点的前k个节点,然后得到这前k个节点的位置,一直将当前节点遍历到最后节点,我们就可以得到整个链表的第k个节点的倒数第k个节点了


23.链表中环的入口节点

思路:

1)一个链表判环可以通过快慢指针来进行判断,一个慢指针一次移动一个位置,快指针可以一次移动二个位置,如果二个指针能过相遇,就说明链表存在环形

2)而且快慢指针相遇的点肯定在环中,所以固定一个指针不动,让另一个指针继续向后移动,记录移动的步数,也就是说记录环长,或者说记录环中节点的个数,

3)然后设置二个指针p1和p2,一个指针就放在头结点位置,另一个指针走环长的长度,然后二个指针均向后移动,以一个位置的速度向后移动,当二个指针相遇的时候,这个相遇的位置就是环的入口节点


25.合并二个排序的链表

思路:二个链表分别是已经排序之后的,那么我们就可以每次得到二个链表中较小的链表,然后不断向后迭代,得到整个链表的排序链表,然后需要考虑的是,如果一个链表已经到尾节点了,另一个节点就直接连接到整个总的排序链表的后面就可以了


35.复杂链表的复制

思路:复杂链表是具有二个指针,一个向后的指针next,一个random,随意指向其他节点或者不指,

我们首先对单链表进行复制,复制每一个节点,然后将复制的结点连接到被复制的结点的后面

然后在复制random指针,复制结点的random指针指向原结点的random指针的下一个节点

最后将原来节点与复制的节点进行分离,就是将原来的结点或者next连接到原来链表的next上,复制的next连接到正确的位置即可


52. 二个链表的第一个公共节点

思路:二个单链表相交,肯定是y字形相交的,那么相交之后的结点个数肯定是一样的,那我们就可以得到这二个链表的长度,然后算出差值,然后从长链表的差值个位置向下遍历,然后就可以得到相交的那个公共节点


18.删除链表的结点

18_1. O(1)时间内删除链表结点

思路:之前看到的删除链表结点都是需要知道要删除的结点的前一个节点,这样直接将前一个节点指向下一个节点即可,但是时间复杂度是O(n)

现在需要时间复杂度是O(1),假设设置要删除的节点为delete,我们将delete节点的下一个节点复制到delete节点上,然后删除delete节点的下一个节点。

18_2. 删除链表中的重复的结点

思路:我们需要保证一个要删除节点的前一个节点pre,而且头结点也有可能被删除

所以我们需要新建一个节点,这个节点的next指向头结点的,pre初始时也指向这个节点,

然后我们要保证二点:

1)当前节点与下一个节点不同时,pre为当前节点

2)当前节点与下一个节点相同,pre不动,不变成当前节点,而是其next指向下一个与当前节点不同的节点

(需要仔细考虑下指针的指向)




猜你喜欢

转载自blog.csdn.net/Lollipop66/article/details/80958898
今日推荐