数据结构--单链表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;

}
相关推荐
努力写代码的熊大41 分钟前
链式二叉树数据结构(递归)
数据结构
yi.Ist42 分钟前
数据结构 —— 键值对 map
数据结构·算法
爱学习的小邓同学42 分钟前
数据结构 --- 队列
c语言·数据结构
s153351 小时前
数据结构-顺序表-猜数字
数据结构·算法·leetcode
闻缺陷则喜何志丹1 小时前
【前缀和 BFS 并集查找】P3127 [USACO15OPEN] Trapped in the Haybales G|省选-
数据结构·c++·前缀和·宽度优先·洛谷·并集查找
lifallen7 小时前
Paimon LSM Tree Compaction 策略
java·大数据·数据结构·数据库·算法·lsm-tree
秋说12 小时前
【PTA数据结构 | C语言版】线性表循环右移
c语言·数据结构·算法
minji...15 小时前
数据结构 算法复杂度(1)
c语言·开发语言·数据结构·算法
black_blank16 小时前
st表 && csp37 第四题 集体锻炼
java·数据结构·算法
我爱Jack16 小时前
Java List 使用详解:从入门到精通
java·开发语言·数据结构