本文主要总结链表算法中常用技术点
有序链表
1、合并有序链表
将两个有序链表合并为一个新的有序链表并返回,新链表是通过拼接给定的两个链表的所有节点组成的。
见https://leetcode-cn.com/problems/merge-two-sorted-lists/
该算法主要就步骤是:
(1)确定链表头结点
第一种方法可以判断哪个链表头大或者小,选择其中一个座位头结点;第二种方法是创建一个新节点,他的next指向头结点
(2)选择结点放在新链表中(升序为例)
两个指针分别指向两个链表,一次比较两个指针结点的值,将小的节点放在新链表后面,并将指向这个节点的指针后移
(3)将没有遍历完成的队列放在新链表后面
2、链表排序
链表排序使用的是归并排序,该算法主要步骤如下:
(1)找到中间位置
使用快慢指针的方法找到中间节点,注意快节点的初始值为head->next,如果为fast=head的时候 当只有两个节点会出现无限循环( sortList)
(2)中间节点左右两部分进行有序链表合并操作
return mergerList(sortList(head), sortList(fast));,该算法由于递归会最终递归到2个节点排序,4个节点排序,依次类推完全符合归并排序的思路见(https://leetcode-cn.com/problems/sort-list/)
反转链表
1、 反转链表
反转链表有两种方法
(1)指针法
思路是不断在老的链表中摘取节点,放在新链表的前面。
head指针指向新链表头结点、q指针指向老链表的头结点,r指向老链表头结点的下一个节点
(2)栈结构
由于栈是先进后出,所以刚好满足反转,不过该方法的空间和时间复杂度高一些
2、 链表相加
链表相加就是数字相加,数据现加是从低位向高位进位,所以需要先把链表倒置,然后从前向后依次相加,注意进位;最终相加完再将链表倒置即可(https://leetcode-cn.com/problems/reverse-linked-list-ii/ https://leetcode-cn.com/problems/reverse-linked-list/)
3、 链表回文
(1)后半部分倒转
先使用快慢指针找到中间位置,找到以后将后半部分进行倒转,倒转以后跟前半部分一一对比即可
(2)前半部分倒转
使用快慢指针找到中间部分,找的过程中用栈存储慢指针数据,注意快指针最后是否为空,不为空说明为奇数个节点,中间指针在向前移动一步,后半部分跟栈中数据进行比较即可
https://leetcode-cn.com/problems/palindrome-linked-list/
删除链表
由于删除数据可能会删除头结点数据,当删除头结点数据的时候不是很好操作,所以一般删除操作都会引入辅助结点,创建一个新节点,该节点的next为head,最后再删除该节点即可
1、 删除重复数据
链表中有重复的元素,删除所有重复元素或者删除重复元素使其不重复(https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/ https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/)
2、删除倒数第n个节点
两个指针一个指向辅助节点,一个指向头结点,然后先将指向头结点向后移动n个节点
之后两个指针同时向前移动,当指向头结点的指针指向尾部NULL时,指向辅助节点的next刚好为倒数第n个节点
3、 移除元素
没有给定链表,仅仅是给定了链表中执行删除的元素,并将该元素删除,
void deleteNode(ListNode* node) {
ListNode* tmp=node->next;
node->val=tmp->val;
node->next=tmp->next;
delete(tmp);
}
相交链表
1、判断链表是否有环,有环的话找到相交点
快慢指针相遇点到入环点的距离 = 头结点到入环点的距离”:将头结点到入环点的这一段环绕在环上,那么快慢指针相遇点即为出发点,即快慢指针相遇点到入环点的距离,等于头结点到入环点的距离。 步骤一:判断是否有环:快慢指针 步骤二:找出入环点:双指针
ListNode *detectCycle(ListNode *head) {
if(head==NULL or head->next==NULL) return NULL;
ListNode* fast=head;
ListNode* slow=head;
while(fast!=NULL && fast->next!=NULL){
fast=fast->next->next;
slow=slow->next;
if(fast==slow ) {
slow=head;
while(slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}
}
return NULL;
}
https://leetcode-cn.com/problems/linked-list-cycle-ii/
2、两个链表相交,求相交点
这个是没有环的相交,求该相交点的方式是:先得到两个链表的长度,然后求出差值diff,长链表指针先走diff步,然后两个链表指针一起走,两个指针第一次相同的位置就是相交处
https://leetcode-cn.com/problems/intersection-of-two-linked-lists/
链表类型主要是这么多,后续发现新题型在继续添加