数据结构(4)单链表算法题(上)

一、移除链表元素

1、题目描述

https://leetcode.cn/problems/remove-linked-list-elements

2、算法分析

思路1:遍历链表找值为val的结点,执行删除指定位置数据的操作

时间复杂度为O(N^2),因此不提倡。

思路2:空间换时间

创建新链表,遍历原链表,将值不为val的节点拿下来尾插

根据思路2,我们可以写出代码

cpp 复制代码
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) 
{
    //创建空链表
    ListNode* newHead = NULL;
    ListNode* newTail = NULL;

    ListNode* pcur = head;
    while(pcur)
    {
        //把值不为val的结点尾插到新链表中
        if(pcur->val != val)
        {
            //尾插
            //链表为空
            if(newHead == NULL)
            {
                newHead = pcur;
                newTail = pcur;
            }
            else
            {
                //链表非空
                newTail->next = pcur;
                newTail = newTail->next;
            }
        }
        pcur = pcur->next;
    }
    //pcur为空
    return newHead;
}

看似思路没有任何问题,但是OJ平台提示有一处解答出错

这是什么原因呢?其实,我们并没有真的向系统申请新空间来创建新链表。newHead和newTail指针指向的都是pcur所指向的链表,当我们把5这个节点"尾插"下来之后,5这个节点的next指针仍然指向6这个节点,因此最后结果会多一个6出来。因此,我们需要把最后一个尾插的节点的next指针置为NULL,也就是newTail->next = NULL。但又带来一个问题,newTail指针不能为空,否则这行代码就是对空指针解引用,所以还要进行判断。

3、参考代码

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) 
{
    //创建空链表
    ListNode* newHead = NULL;
    ListNode* newTail = NULL;

    ListNode* pcur = head;
    while(pcur)
    {
        //把值不为val的结点尾插到新链表中
        if(pcur->val != val)
        {
            //尾插
            //链表为空
            if(newHead == NULL)
            {
                newHead = pcur;
                newTail = pcur;
            }
            else
            {
                //链表非空
                newTail->next = pcur;
                newTail = newTail->next;
            }
        }
        pcur = pcur->next;
    }
    //pcur为空
    if(newTail)
        newTail->next = NULL;
    return newHead;
}

二、反转链表

1、题目描述

https://leetcode.cn/problems/reverse-linked-list

2、算法分析

思路1:创建新链表,遍历原链表,每个节点头插到新链表中。

该思路很容易想到,代码实现也很简单,就不过多赘述,这里分享一个更优的解法~

思路2:创建三个指针

创建三个指针n1,n2,n3。n1初始值为NULL,n2指向链表的头结点,n3指向n2的下一个结点。只要n2不为空,就把n2的next指针指向n1。接下来,n1指向n2,n2指向n3,n3指向n3的下一个节点。继续重复刚才的步骤,直到n2为NULL,此时n1就是反转之后的链表的头结点。

3、参考代码

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) 
{
    //链表为空
    if(head == NULL)
    {
        return head;
    }
    //创建三个指针
    ListNode* n1 = NULL;
    ListNode* n2 = head;
    ListNode* n3 = n2->next;

    while(n2)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n3)
            n3 = n3->next;
    }
    return n1;
}

三、链表的中间结点

1、题目描述

https://leetcode.cn/problems/middle-of-the-linked-list

2、算法分析

思路1:求链表的总长度,总长度除以2求出中间节点的位置,返回中间位置的节点

时间复杂度为O(N),代码实现很简单,不做过多赘述,下面分享一个更优的解法~

思路2:快慢指针

定义两个指针,初始值都指向头结点。慢指针(slow)每次走一步,快指针(fast)每次走两步。

3、参考代码

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) 
{
    //定义快慢指针
    ListNode* slow = head;
    ListNode* fast = head;

    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    //fast为空或者fast->next为空就跳出循环
    return slow;
}

***注意:while循环条件里的代码不可以写成fast->next && fast !!!***看似只是调换了一下顺序,但是两个代码会有很大的区别。因为此时循环条件会优先判断fast->next,当链表是偶数个节点时,fast指针为空时,此时fast指针为NULL,fast->next就是对空指针解引用,程序一定会报错。

相关推荐
爱装代码的小瓶子3 小时前
数据结构之队列(C语言)
c语言·开发语言·数据结构
aramae6 小时前
大话数据结构之<队列>
c语言·开发语言·数据结构·算法
cccc来财7 小时前
Java实现大根堆与小根堆详解
数据结构·算法·leetcode
刚入坑的新人编程9 小时前
暑期算法训练.9
数据结构·c++·算法·leetcode·面试·排序算法
找不到、了11 小时前
Java排序算法之<选择排序>
数据结构·算法·排序算法
小徐不徐说11 小时前
动态规划:从入门到精通
数据结构·c++·算法·leetcode·动态规划·代理模式
guguhaohao12 小时前
排序算法,咕咕咕
数据结构·算法·排序算法
晚云与城12 小时前
【数据结构】二叉树初阶详解(二):实现逻辑与代码拆解(超详版)
数据结构
小新学习屋12 小时前
《剑指offer》-数据结构篇-树
数据结构·算法·leetcode
此心安处是吾乡102412 小时前
数据结构 双向链表
数据结构·链表