关于链表问题

转载自https://leetcode-cn.com/circle/article/YGr54o/

(一)双指针思路:

19. 删除链表的倒数第N个节点

快慢指针法:设置虚拟节点 dummy指向 head,设定双指针 fast 和 slow,初始都指向虚拟节点 dummy。移动 fast,直到 slow 与 fast 之间相隔的元素个数为 n ,再同时移动 slow 与 fast,直到 fast 指向的为 NULL,将 slow 的下一个节点指向下下个节点即可。

86. 分隔链表

双指针法,before_head 链表存放比 x 小的节点,after_head 链表存放比 x 大于或等于的节点,我们分别用 before 和 after 来前面两个链表添加节点,用 head 来遍历原始链表。当原始链表遍历完成时,我们需要将 before_head 链表连接上 after_head 链表,即 before->next=after_head->next;after->next=nullptr;

92. 反转链表 II※※

双指针法,第一步:找到待反转节点的前一个节点。
第二步:反转m到n这部分。
第三步:将反转的起点的next指向反转的后面一部分。
第四步:将第一步找到的节点指向反转以后的头节点。
https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/ji-bai-liao-100de-javayong-hu-by-reedfan-6/

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode node = dummy;
        //找到需要反转的那一段的上一个节点。
        for (int i = 1; i < m; i++) {
            node = node.next;
        }
        //node.next就是需要反转的这段的起点。
        ListNode nextHead = node.next;
        ListNode next = null;
        ListNode pre = null;
        //反转m到n这一段
        for (int i = m; i <= n; i++) {
            next = nextHead.next;
            nextHead.next = pre;
            pre = nextHead;
            nextHead = next;
        }
        //将反转的起点的next指向反转的后一部分
        node.next.next = next;
        //需要反转的那一段的上一个节点的next节点指向反转后链表的头结点
        node.next = pre;
        return dummy.next;
    }
}

109. 有序链表转换二叉搜索树

快慢指针法:问题的关键是找到链表的中间元素,使用两个指针,慢指针每次向后移动一个节点,快指针每次移动两个节点。当快指针到链表的末尾时,慢指针正好访问到链表的中间元素。这时候把中间位置的节点的值作为二叉搜索树根节点的值。(因为二叉搜索树对应的就是一个有序数组,根节点对应的元素值为为有序数组最中间的位置。),然后将链表从中间元素的左侧断开,递归调用即可。

141. 环形链表

快慢指针法:定义两个指针,一快一慢,快指针每次走两步,慢指针每次走一步。如果链表中不存在环,最终快指针将会最先到达尾部,此时返回 false。如果链表中存在环,那么快指针最终一定会追上慢指针。

142. 环形链表 II

快慢指针法:定义两个指针,一快一慢,快指针每次走两步,慢指针每次走一步。如果链表中不存在环,最终快指针将会最先到达尾部,此时返回 false。如果链表中存在环,那么快指针最终一定会追上慢指针。然后相遇之后将 fast 指针指向头节点,slow 指针指向相遇点,每次各走一步,两个指针必定相遇,且相遇第一点为环入口点。

143. 重排链表

双指针法:首先重新排列后,链表的中心节点会变为最后一个节点,所以需要使用快慢指针法找到链表中间节点,分割成左右两个链表,反转右半部分链表,依次连接两个链表节点即可。

160. 相交链表

双指针法:指针 pA 指向 A 链表,指针 pB 指向 B 链表,依次往后遍历
如果 pA 到了末尾,则 pA = headB 继续遍历
如果 pB 到了末尾,则 pB = headA 继续遍历
比较长的链表指针指向较短链表head时,长度差就消除了。
通俗来讲的意思是:我先走我的路,再走你的路,你先走你的路,再走我的路,这样咱俩走的路程就一样了,速度一样,那么肯定在咱俩两条路的交叉口相遇,并一起走向终点。

206. 反转链表

双指针法:指针 pre 用来表示前驱节点,指针 cur 用来遍历链表,每次循环改变将 pre->cur 的方向改变为 pre<-cur,直到遍历结束。

234. 回文链表

快慢指针法:使用快慢指针找到链表中点,反转链表后半部分,比较两个半长链表
是否相同。

876. 链表的中间结点

快慢指针法:使用快慢指针找到链表中点。while(fast != null && fast.next != null)

(二)链表经典题目

2. 两数相加

模拟题,由于链表是逆序存放数字的,所以链表数字从左至右低位对低位,高位对高位,因此我们从左至右遍历两个链表模拟加法运算即可,注意向高位进位。

21. 合并两个有序链表

模拟题,每次循环比较 l1->val和l2->val,若 l1->val<l2->val,则在 cur 后面添加 l1;否则在 cur 后面添加 l2。

23. 合并K个排序链表困难(没做过)

方法1:分治法,将 k 个链表利用二分分为 k 个独立子链表,然后两两进行合并,最后形成一个排序链表。方法2:优雅的暴力法,利用队列 queue 来实现两两链表的组合,首先将队列前两个链表合并成一个,然后添加到队列的尾部,直到队列中只有一个链表时,表示 k 个链表已经合成了。

24. 两两交换链表中的节点中等

简单递归,每次递归交换 head 与 next 即可,也就是完成了两两交换链表中的节点。

25. K 个一组翻转链表困难(没做过)

分治法,将链表按长度 k 进行分组,然后每次翻转长度 k 的链表,注意翻转了长度 k 的链表后新链表的尾部还要连接未翻转部分。

61. 旋转链表中等

模拟题,先求出链表长度 size,若 k 取余 size 为空,那么不用旋转了,直接返回 head;否则先让快指针走 k 个位置,然后两个指针一起走完整个链表。这时,两个指针之间的区域就是我们要移动的区域,只要更改指针指向,就完事了。
即,first->next 指向 head,完成旋转(当然还没完事);
head 指向 second->next,头结点指向确认;
second->next 指向空节点,尾结点指向确认;
打完收工。
链接:https://leetcode-cn.com/problems/rotate-list/solution/shou-hui-man-hua-tu-jie-leetcodezhi-xuan-zhuan-lia/

82. 删除排序链表中的重复元素 II

模拟题,遍历链表,若 head 的节点值与 head 的 next 节点值不相等,则 pre 指向 head,也就是不重复节点;若相等,我们需要找到重复值子链表的最后一个节点,然后令 pre 指向 head->next,同时 head 移动到下一个节点。

83. 删除排序链表中的重复元素简单

模拟题,直接遍历链表,遇到重复值的节点删除即可。

138. 复制带随机指针的链表

模拟题,分三步,第一步在原链表的每个节点后面拷贝出一个新的节点,第二步拷贝 random,第三步断开链表。

203. 移除链表元素简单

模拟题,直接遍历链表确定是否删除节点即可。

445. 两数相加 II

逆序处理所有数位,使用两个栈法,将两个链表节点值全部压入栈中,然后每次去栈顶元素进行相加,因为这样保证了低位和低位相加,不会出现错位现象。最后直到两个栈为空且进位为 0 为止,就表示相加完成了。

725. 分隔链表(没做出来)

模拟题,首先求出链表的长度,然后根据k来求得每段链表的平均长度,顺便求出余数。由于题目要求每部分长度相差不能超过 1,而且排在前面的部分长度要大于后面部分的长度,所以我们根据余数的个数,给排在前面的部分长度 +1。

430. 扁平化多级双向链表(没做出来)

模拟题,迭代法,遍历链表,若发现该链表存在 child 节点那么就将 [child,tail]` 这段子链表插入到当前节点的后面去,然后继续遍历链表。

817. 链表组件(没有做)

模拟题,如果当前的节点在列表 G 中,并且下一个节点不在列表 G 中,我们就找到了一个组件的尾节点,将 res 加 1。

1171. 从链表中删去总和值为零的连续节点

模拟题,直接遍历链表进行删除和为 0 的连续子链表。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容