数据结构--单链表OJ题

例1:反转链表

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

解:这道题有递归和迭代两种反转链表的方式。

如果是迭代的话,我们需要使用的是三指针法。首先保证链表不为空,然后创建三个指针(n1、n2、n3),开始时将n1赋值为NULL,n2赋值为head,n3赋值为head->next。 随后进行链表遍历,先让n2->next = n1,然后n1 = n2、n2=n3、当n3!= NULL时,n3也向后移动一个节点,即n3 = n3->next。在循环结束后,n1就是我们新的头结点。

cpp 复制代码
struct ListNode* reverseList(struct ListNode* head) 
{
    if(head == NULL)
    {
        return head;
    }
   else
   {
     //三指针法
    struct ListNode*n1;
    struct ListNode*n2;
    struct ListNode*n3;
    n1 = NULL;
    n2 = head;
    n3 = head->next;
    //
    while(n2)//n2 = NILL时退出循环
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n2)
        {
        n3 = n2->next;
        }
    }
    return n1;//返回新的头节点
   }
}

如果是递归法的话,我们首先要判断链表的头结点和其下一个节点是否为空,如果为空就不需要反转,直接返回头指针;如果不为空,我们就再次调用本函数,但是参数变成了head->next。随后我们将当前节点的下一个节点的指针指向当前节点,然后将当前节点的指针置为空指针。代码如下:

cpp 复制代码
// 递归反转链表函数
struct ListNode* reverseList(struct ListNode* head) 
{
    if (head == NULL || head->next == NULL) 
    {
        return head;
    }

    // 递归调用反转链表的函数
    struct ListNode* new_head = reverseList(head->next);

    // 将当前节点的下一个节点的指针指向当前节点,然后将当前节点的指针指向空
    head->next->next = head;
    head->next = NULL;

    return new_head;
}

例2:移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

提示:

  • 列表中的节点数目在范围 [0, 10^4]
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

解:这道题你可以选择删除链表中的元素,但我个人认为创建新链表是更简单的方法。

首先我们创建好新的头指针(newhead)和尾指针(newtail)并赋值为NULL,考虑原链表是否为空是必不可少的一步,然后我们就要开始尾插节点了。我们创建一个pcur的临时变量来代替头指针进行遍历链表的操作。当pcur->val不等于val时,我们就尾插代码,这里尾插代码分为空链表的尾插,和非空链表的尾插,空链表的尾插就是newhead=NULL时,我们将newhead和newtail都赋值为第一个不为val的节点,成为非空链表之后,我们就进行简单的尾插就可以了。在循环结束后我们要记得把newtail->next置为空。代码如下:

cpp 复制代码
struct ListNode* removeElements(struct ListNode* head, int val) 
{
    struct ListNode* newhead = NULL;
    struct ListNode* newtail = NULL;
    //空链表
    if(head == NULL)
    {
        return NULL;
    }
    //非空链表
    struct ListNode* pcur = head;
    while(pcur)
    {
        if(pcur->val != val)
        {
            if(newhead == NULL)
            {
                newhead = newtail = pcur;
            }
            else
            {
                newtail->next = pcur;
                newtail = newtail->next;
            }
        }
        pcur = pcur->next;
    }
    if(newtail)
        newtail->next = NULL; 

    return newhead;
}

例3:链表的中间节点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

提示:

  • 链表的结点数范围是 [1, 100]
  • 1 <= Node.val <= 100

解:

这道题我推荐使用快慢指针来做,快和慢只是形容词。我们创建两个指针(slow和fast),将两个指针都赋值为头指针head,然后进行循环,slow一次前进一个节点,fast一次前进两个节点,当fast或者fast->next为空指针时,循环结束,而slow指向的节点就是中间节点。

代码演示:

cpp 复制代码
struct ListNode* middleNode(struct ListNode* head) 
{
    //快慢指针
    struct ListNode* slow,*fast;
    slow = head,fast = head;

    //慢指针走一步,快指针走两步,fast到头就停止循环
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;

}
相关推荐
wheeldown5 小时前
【数据结构】选择排序
数据结构·算法·排序算法
躺不平的理查德9 小时前
数据结构-链表【chapter1】【c语言版】
c语言·开发语言·数据结构·链表·visual studio
阿洵Rain9 小时前
【C++】哈希
数据结构·c++·算法·list·哈希算法
Leo.yuan9 小时前
39页PDF | 华为数据架构建设交流材料(限免下载)
数据结构·华为
半夜不咋不困10 小时前
单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构
数据结构·链表
忘梓.10 小时前
排序的秘密(1)——排序简介以及插入排序
数据结构·c++·算法·排序算法
y_m_h13 小时前
leetcode912.排序数组的题解
数据结构·算法
1 9 J13 小时前
数据结构 C/C++(实验三:队列)
c语言·数据结构·c++·算法
921正在学习编程13 小时前
数据结构之二叉树前序,中序,后序习题分析(递归图)
c语言·数据结构·算法·二叉树
毕竟秋山澪13 小时前
岛屿数量 广搜版BFS C#
数据结构·算法·宽度优先