1024狂欢力扣经典链表OJ题合集

Posted 东条希尔薇

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1024狂欢力扣经典链表OJ题合集相关的知识,希望对你有一定的参考价值。

现在的力扣题的源代码我会全部一并上传至我的码云仓库里面,点我看仓库

写在前面
首先祝各位程序猿1024狂欢节快乐鸭!这是属于我们的节日

为了致敬1024,今天的力扣系列不再是一题了,而是多个题的组合

也是与我们最近更新的内容梦幻联动


206题:反转链表

题目描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

例如:
1->2->3->4->5
我们要返回5->4->3->2->1

思路求解

此题我们有两个方法求解

指针反转法

设我们有这个链表

我们可以想到,要反转链表,我们可以尝试去反转指针的指向

一个一个的反转,直到反转到末尾就行了


说起简单,我们其实要考虑很多细节

  1. 题目说的是单链表,我们不能直接找到前面的结点,所以需要一个指针指向当前指针的前面结点
  2. 改变指向后,我们无法找到后面的结点了,所以还需要另外一个指针指向当前指针后面的结点

所以这里我们需要三个指针,prev,cur,next

初始化:
prev先指向空,cur指向head,next指向head->next

遍历方法图解:


结束条件,cur为空时,但要注意,cur为空时,不能移动next了,因为这会导致空指针解引用的错误,具体在代码中说明

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseList(struct ListNode* head){
    if(!head)
        return NULL;//这里是空链表的情况
    struct ListNode* prev=NULL,*cur=head,*next=head->next;
    while(cur)
    {
        cur->next=prev;
        prev=cur;
        cur=next;
        if(next)
            next=next->next;//这里是判断cur是否走向末尾,走向末尾就不能移动next了
    }
    return n1;
}

头插法

我们可以重新定义一个链表出来

我们从头遍历链表,并把结点头插至新链表中

画图求解

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseList(struct ListNode* head){
    if(!head)
        return NULL;
    struct ListNode* newhead=NULL,*cur=head,*next=head->next;
    while(cur)
    {
        cur->next=newhead;
        newhead=cur;
        cur=next;
        if(next)
        {
            next=cur->next;
        }
        
    }

    return newhead;
}

876题 链表的中间结点

题目描述

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

思路求解:

这是一个比较典型的快慢指针的问题,虽然思路比较简单,但是真的不容易想到啊(默默流泪)

我们知道,一个中点在数学上什么特征?


上图,我们显然有2AC=AB

所以我们也利用了中点的特性

定义两个指针fast和slow,其中fast每次走两步,slow每次走一步

当fast走向末尾或者走向倒数第一个结点时,slow所指向的位置就是中点

黄色标记的是为什么呢?

因为我们有链表长度为奇数和偶数的情况

同样,我们画图求解

这是偶数个结点的情况

这是奇数个结点的情况

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* middleNode(struct ListNode* head){
    struct ListNode*fast=head,*slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    return slow;
}

剑指offer 22.链表倒数第K个结点

题目描述

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

思路求解

因为单链表只能顺着走,无法倒着走

所以我们顺着这个思路思考,我们也同样正着走

这也是一个双指针问题

跟上一个题有异曲同工之妙

我们可以先让fast指针先走k步,这样的目的是保证fast和slow相差k个距离

fast走完k步后,slow和fast同时走

结束条件:fast走向链表的末尾

图解

代码实现

/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 * };
 */
 
/**
 *
 * @param pListHead ListNode类
 * @param k int整型
 * @return ListNode类
 */
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    // write code here
    struct ListNode* fast=pListHead,*slow=pListHead;
    while(k--)
    {
        if(!fast)
        {
            return NULL;
        }
        fast=fast->next;
        
    }
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow;
}

21 合并两个有序链表

题目描述

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

思路求解

这个跟数组的合并思路差不多,我在这篇博客中讲到过

思路就是定义两个指针分别指向两个链表,然后比较大小,谁小就尾插进我们定义的新链表中。

结束条件是l1,l2其中一个指针指向空,然后直接链接剩下的结点即可

在这里,为了防止新链表为空带来的种种问题,我们在这里引入一个哨兵位头结点

画图求解


代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    if(!l1)
        return l2;
    if(!l2)
        return l1;
        //上面是其实一个链表为空的情况
    struct ListNode* head=malloc(sizeof(struct ListNode));//开设头结点
    struct ListNode* tail=head;//为尾插定义的
    while(l1&&l2)
    {
        if(l1->val<l2->val)
    {
        tail->next=l1;
        l1=l1->next;
        tail=tail->next;
    }
    else
    {
        tail->next=l2;
        l2=l2->next;
        tail=tail->next;
    }
    }

    if(!l1)
    {
        tail->next=l2;
    }
    if(!l2)
    {
        tail->next=l1;
    }//链接剩余的元素
    

    struct ListNode* newhead=head->next;
    free(head);
    return newhead;
}

点我直通1024小调查嘻嘻嘻

以上是关于1024狂欢力扣经典链表OJ题合集的主要内容,如果未能解决你的问题,请参考以下文章

Chain Surfase Test - java 链表经典 OJ 面试题 - 巨细

[ 链表OJ题--C语言] 相交链表 两个链表的第一个公共结点

链表12道经典OJ题——助你理解链表原理

「LeetCode合集」链表(List)及经典问题

「LeetCode合集」链表(List)及经典问题

OJ练习第60题——合并 K 个升序链表