拿捏链表(二)-------反转链表

简介: 拿捏链表(二)-------反转链表

题目描述

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

思路一:

反转一个单向链表,我们可以看成是将链表中的每个结点的指向反向(也就是说从后一个结点指向前一个结点)。

我们在考虑情况的时候,还是分两种情况:先考虑一般情况,再考虑极端情况。

1.考虑一般情况

思考一下:建立两个指针变量,我们如果直接让后一个结点指向前一个结点,那么后一个结点所指向的再后面一个结点的位置是不是不确定吧?

因此,我们需要定义3个指针变量:p1,p2,p3 。

p1:记录指针指向将要反转的结点反转后要指向的位置。

p2:记录指针指向将要反转的结点。

p3:记录指针指向将要反转的结点的下一个结点。

在反转时,我们首先让p2指向的结点指向p1指向的位置,其次让p1,p2,p3指针统一后移.

如此往复。

2.考虑特殊情况

特殊情况也就是对边界进行分类讨论,有三种1情况:反转第一个结点指针的指向,反转最后一个结点指针的指向,传入的链表为空时的情况。

2.2当链表的最后一个节点为待移除的节点时:

p2记录的是指针指向将要反转的结点,所以当反转第一个结点指针的指向时,p2指针便指向的就是第一个结点。

反转过程中是让p2指向的结点指向p1指向的位置,所以我们只需用将p1的初始值赋值为NULL即可。这样,反转后就让第一个结点指针指向NULL了(也就是说反转后的最后一个结点指向空)。

2.2当链表的最后一个节点为待移除的节点时:

当最后一个结点的指针指向被反转时,p2刚好指向了最后一个结点,在指针反转完成之后,p1,p2,p3指针统一向后移动.

我们可以基本上是没有问题的,而且此时也发现遍历链表时的终止条件需要返回的新的头指针, 需要返回的新的头指针,也就是当p2指针为NULL时停止遍历,并且返回p1指针指向的位置。

我们这里需要注意,这时这3个指针统一后移动时,p3指针的后移将会失败,p3后移前指向的是NULL,因此我们后移p3指针前需判断其是否为空。

2.3当传入的链表为空时:

如果传入的链表为空,我们根本不需要对链表进行任何操作,直接返回传入的头指针就可解决。(只有一个节点时也满足)

代码实现

struct ListNode
 {
  int val;
  struct ListNode *next;
};
struct ListNode* reverseList(struct ListNode* head)
{
  if (head == NULL || head->next == NULL)              //当链表为空或只有一个结点时,无需操作
  {
      return head;                                     //直接返回
  }                                 
  struct ListNode* p1 = NULL;                           //记录指针指向将要反转的结点反转后要指向的位置。
  struct ListNode* p2 = head;                           //记录指针指向将要反转的结点。
  struct ListNode* p3 = head->next;                     //记录指针指向将要反转的结点的下一个结点。
  while (p2)                                             //p2为NULL时,停止遍历
  {
    p2->next = p1;                                      //反转结点指向
    p1 = p2;                                            //指针后移
    p2 = p3;                                            //指针后移
    if (p3)                                             //判断p3是否为NULL
    {
         p3 = p3->next;                              //指针后移
    }                                   
  }
  return p1;                                              //返回p1指针指向的位置
}

思路二:

将原链表的结点,从头到尾遍历完,然后一个一个拿下来头插到一个新链表中。(这个新链表起始时为一个空链表)

直到遍历完为止。

代码实现

struct ListNode 
{
  int val;
  struct ListNode *next;
};
struct ListNode* reverseList(struct ListNode* head)
{
  struct ListNode* cur = head;                                   //记录当前待头插的结点
  struct ListNode* newhead = NULL;                               //新链表初始时为空
  while (cur)                                                    //链表中结点头插完毕时停止循环
  {
    struct ListNode* next = cur->next;                         //记录下一个待头插的结点
    cur->next = newhead;                                       //将结点头插至新链表
    newhead = cur;                                             //新链表头指针后移
    cur = next;                                                //指向下一个待头插的结点
  }
  return newhead;                                                //返回反转后的头指针
}

文章到这里就结束了,有更好的思路或问题的,欢迎留言评论区。

下期预告:拿捏链表(三)-----------链表的中间节点

相关文章
|
9月前
|
索引
【力扣刷题】两数求和、移动零、相交链表、反转链表
【力扣刷题】两数求和、移动零、相交链表、反转链表
62 2
【力扣刷题】两数求和、移动零、相交链表、反转链表
|
算法
【LeetCode力扣】234 快慢指针 | 反转链表 | 还原链表
【LeetCode力扣】234 快慢指针 | 反转链表 | 还原链表
104 0
|
算法 索引
带你拿捏链表
带你拿捏链表
132 0
|
测试技术
【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
98 0
|
9月前
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点.
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点
92 1
|
9月前
|
C++
[leetcode 链表] 反转链表 vs 链表相交
[leetcode 链表] 反转链表 vs 链表相交
|
9月前
|
C语言 C++ 索引
【力扣】141. 环形链表、160. 相交链表、206.反转链表、234. 回文链表
【力扣】141. 环形链表、160. 相交链表、206.反转链表、234. 回文链表
|
9月前
|
C语言
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】
|
9月前
|
Python 索引 Java
Python每日一练(20230406) 环形链表 II、反转链表、子集 II
Python每日一练(20230406) 环形链表 II、反转链表、子集 II
42 0
Python每日一练(20230406) 环形链表 II、反转链表、子集 II
|
9月前
|
存储 算法 Java
【数据结构与算法】2、链表(简单模拟 Java 中的 LinkedList 集合,反转链表面试题)
【数据结构与算法】2、链表(简单模拟 Java 中的 LinkedList 集合,反转链表面试题)
79 0