leetcode链表习题总结

1.链表题中经常给链表添加一个假头,使得头结点也能受到检查
2.链表的遍历通常设定一个指针指向头部,然后遍历直至指针指的结点不为Null

ListNode cur = head;
while(cur != null)
{
    ....
    cur = cur.next;
}

3.删除结点操作:构建两个指针,一个指针遍历链表,另一个指针紧跟后面进行删除操作

ListNode fakeHead = new ListNode(0);
fakeHead.next = head;
ListNode pre = fakeHead,cur = head;
while(cur != null && cur.next != null){
    if(cur.val == val)
        pre.next = cur.next;
    else
        pre = pre.next;
    cur = cur.next;
}
return fakeHead.next;

4.翻转链表:
1)构建两个指针,一个指向翻转后结点要指向的结点,另一个遍历原链表

ListNode pre = null,cur = head;
while(cur != null)
{
    ListNode next = cur.next;
    cur.next = pre;
    pre = cur;
    cur = next;
}

2)在指定的位置翻转链表:
“遍历头插法”:如果只知道待翻转结点的前结点。
一个指针用来指向待翻转结点的前一个结点(pre),固定,一个指针用来指示待翻转结点(cur),一个指针用来保持结点转移后原链表的次序(start)

while(cur != null && i < n)//i用来指示翻转的次数
{
    ListNode next = cur.next;
    cur.next = pre.next;
    start.next = next;
    pre.next = cur;
    cur = next;
    i++;
}

“删除尾插法“:如果知道待翻转的第一个结点的前结点和尾结点。
pre之后的一个结点为待删除结点,pre直接指向待删除结点之后,将待删除结点插入tail之后,知道pre.next != tail
这里写图片描述
3)成对的翻转链表:构造假头,用一个指针指示待翻转的结点对的前一个结点,两个指针分别指示待翻转的两个结点
4)以k个结点为一组翻转链表,不足k个的不用翻转:为每组带翻转的结点创建一个头结点pre,遍历数组,记数,使tail指针停留在下一次需要翻转的结点之前,如果记数值等于k值,则进行翻转,否则不用翻转。
这里写图片描述
5.判断是否有环:构建一个储存结点的散列集(HashSet),将遍历链表将结点加入,如果当前结点已经存在于set中,则有环。
总之判断链表(s)中是否有同一结点的都可以用散列集
6.判断链表是否为回文结构:将链表分为均等的两半,一个链表倒转,再逐个比对结点的值
将链表分为均等两份的方法:

ListNode slow = head,fast = head;
while(fast != null && fast.next != null)
{
    slow = slow.next;
    fast = fast.next.next;
}
if(fast != null)//链表结点数为奇数
    slow = slow.next;
//得到head和slow两个均等的链表

7.将两个链表相加
a.从左至右相加:构建一个新链表作为和结点的储存,使用sum和carry机理进行求和
这里写图片描述
b.从右向左相加:利用Stack,遍历两个链表将结点分别加入两个Stack中,其余方法类似于a
这里写图片描述
8.如果需要将链表的结点发生大的改动,可以新构造链表,最后将链表按要求接上
a.重新构造原链表,小于x的放在前面,大于x的放后面,相对顺序不变
b.将链表中奇数位的结点放在前面,偶数位的放在后面,相对顺序不变
9.链表的排序
a.插入排序
对于链表,由于没有从后往前的遍历,所以可以创建一个辅助链表,在原链表中遍历,把原链表的元素插入辅助链表中第一个值大于原链表元素的位置(从头到尾寻找),最后返回辅助链表。
这里写图片描述
b.归并排序
分为sort和merge两部分:sort部分是将链表分为两部分,merge新构建一个链表,将结点从小到大加入链表中
这里写图片描述
c.合并k个有序链表
1.归并法,sort k个有序链表,再合并
这里写图片描述
2.优先队列法
可以定义一个容量为k的优先队列,将每个链表的表头加入其中,再将最小值加入结果,如果此节点后还有元素,则再加入优先队列中,维护容量为k的堆
这里写图片描述
10.散列表在链表中的应用
1)深度复制含有随机指针的链表
方法一:
1.将原结点作为散列表的key,而通过原结点的值构建新节点,next和random均为空,将新节点作为value,遍历原链表,得到散列表。
2.遍历原链表,分别设置新节点的next和random,从而得到了拷贝链表
为什么不能用普通链表的拷贝方法?因为如果某结点的random指向的结点还未出现在新链表中,则会出现混乱。在散列表中每个新结点都是创建好的,只是没有确定指针的对关系而已。
这里写图片描述
方法二:
1.将原结点的复制结点都跟在原结点之后
2.遍历链表,根据原结点的random指针处理复制结点的random指针
3.除去原结点,形成复制结点的next指针
这种方法非常巧妙,利用原链表的结构作为新链表的骨架,从而使得不需要额外空间
这里写图片描述
2)重排链表:原链表的顺序为L0L1L2….Ln-1Ln
要求返回L0LnL1Ln-1…
方法一
遍历链表使用散列表储存链表结点的位置与结点本身,并得出结点总数,最后遍历一半的链表按题目要求将结点重置位置
这里写图片描述
方法二
1)找到链表中间位置的前一个结点:1->2->3->4->5->6,结点为3
2)将结点后面的链表翻转:1->2->3->6->5->4
3)逐个排列1->6->2->5->3->4
这里写图片描述

猜你喜欢

转载自blog.csdn.net/zhou373986278/article/details/78223278