文章汇总以链表作为存储结构,常用的一些算法集合。题目皆取自leetcode.
链表基础算法思想
- 双指针(快慢指针)
- 头插、尾插与逆序
- 链表环问题
链表简介
类别:单链表、双链表、循环链表。
链表区别与数组最大的地方在与访问某个特定位置的元素所需要的时间,数组是O(1)而链表只能一个一个遍历故为O(n).
双指针
由于链表的空间是使用new创建,堆中存储,位置变换需要通过指针访问。类似数组中的双指针操作:快慢指针、对撞指针、扩散指针,有些需要额外的指针来实现(双链表)。
- 单链表快慢指针删除链表倒数第k(2)个元素。
思路:链表尾与倒数第k个元素相差k的距离,让快指针先走k的距离,然后快慢指针一起走,快指针到末尾使,慢指针指向该元素。因为两者始终相差k的距离。
删除该元素的话,使用一个伪头结点这样慢指针就可以停在该结点的前驱结点方便删除。
- 双链表
双链表可以使用对撞指针和扩散指针。
头插法与双指针。
创建链表时两种方法,头插法和尾插法,头插法会导致逆序。
- 反转链表
思路:1.头插法建立新链表 2.双指针反转
pre、cur、next三个指针 cur.next=pre,然后依次先后移动指针,直至cur=null
或者可以借助递归的想法,2-5逆序后将1插入尾部。
- K 个一组翻转链表
给定链表head,k个一组反转(不足k不反转)。
思路:借助上题反转思想,和递归的设计思路。
- head开始k个一组逆序,记录逆序后的尾指针cur
- 递归(next.next) -> 返回值head //(逆序后头结点指针)
- cur.next = head; // 逆序完成
链表环问题
- 如何判断链表是否有环
思路:快慢指针。慢指针每次走一步,快指针每次走两步。当有环存在时,快指针总会追上慢指针,就像体育生总会在跑道甩我一圈一样哈哈哈,而直道(无环)就休想追上我
- 如何确定环的位置
思路 :快指针所走距离:a+n(b+c) + b= 2* 慢指针所走距离:a+b
化简得:a=c+(n−1)(b+c) //即a得距离==(n-1)(b+c) + c 。故两指针在第一次相遇后,同时再从起点和相遇点出发,会在入口处相遇。
- 相交链表如何确定相交位置
思路:双指针。两指针分别指向两链表头部,当一个指针到达null时再指向另外一个链表的head,下次两指针就会从距离相交结点相同的位置开始移动。本质上就是走一个(a+b)两链表头结点到相交节点距离和。