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

}
相关推荐
新晓·故知13 分钟前
<基于递归实现线索二叉树的构造及遍历算法探讨>
数据结构·经验分享·笔记·算法·链表
gorgor在码农42 分钟前
Mysql 索引底层数据结构和算法
数据结构·数据库·mysql
武昌库里写JAVA2 小时前
【Java】Java面试题笔试
c语言·开发语言·数据结构·算法·二维数组
一休哥助手3 小时前
Redis 五种数据类型及底层数据结构详解
数据结构·数据库·redis
苏宸啊3 小时前
顺序表及其代码实现
数据结构·算法
lin zaixi()3 小时前
贪心思想之——最大子段和问题
数据结构·算法
夜雨翦春韭3 小时前
【代码随想录Day30】贪心算法Part04
java·数据结构·算法·leetcode·贪心算法
一直学习永不止步4 小时前
LeetCode题练习与总结:H 指数--274
java·数据结构·算法·leetcode·数组·排序·计数排序
Amor风信子4 小时前
华为OD机试真题---跳房子II
java·数据结构·算法
Ljubim.te5 小时前
软件设计师——数据结构
数据结构·笔记