反转单链表@Leetcode--链表

Posted 呀小边同学

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反转单链表@Leetcode--链表相关的知识,希望对你有一定的参考价值。

题目

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

//Definition for singly-linked list:
struct ListNode {
    int val;
    struct ListNode *next;
 };

函数接口:

struct ListNode* reverseList(struct ListNode* head){

}


反转一个单链表: OJ链接

思路一:

改变“箭头”指向

❄️反转?


显然我们需要两个指针来负责反转(n1,n2),然而在反转的同时(n2->next = n1;),原本①和②之间的链接也断开了,这我们就需要第三个指针来记录下一个节点的位置(n3)

因此,我们定义了如下三个指针并初始化

struct ListNode* n1 = NULL;
struct ListNode* n2 = head;
struct ListNode* n3 = head->next;

其中,n1,n2负责反转n3负责记录

n2->next = n1;//反转

❄️ 迭代向后挪动?

挪动过程:

可以很轻易的写出代码:

n1 = n2;
n2 = n3;
n3 = n3->next;

❄️ 终止条件?

快进~

因此在n2->next==NULL时,循环结束(注意,循环括号内,想的是终止条件,写的是进行条件)。

while (n2 != NULL)
{
	//翻转
	n2->next = n1;
	//迭代向后挪
	n1 = n2;
	n2 = n3;
	n3 = n3->next;
}

细心的小伙伴可能已经发现了,在这一次反转之后的迭代挪动中,n3 = n3->next;是对空指针的解引用😱,会崩掉,不过没关系啦,做一下处理就好了!

if(n3 != NULL)
	 n3 = n3->next;


看图!此时,我们要返回链表的头结点为n1

这里给出完整代码:

struct ListNode* reverseList(struct ListNode* head){
    if(head==NULL)
    {
        return NULL;//处理空链表
    }
    //初始条件
    struct ListNode* n1 = NULL;
    struct ListNode* n2 = head;//n1,n2用来交换
    struct ListNode* n3 = head->next;//n3用来记录下一个
    while(n2!=NULL)
    {
        //翻转
        n2->next = n1;
        //迭代向后挪
        n1 = n2;
        n2 = n3;
        if(n3)
            n3 = n3->next;
    }
    return n1;
}

思路二:

🔑 取原链表节点,头插到newhead新链表中去

有过思路一的详细铺垫,思路二分析起来就很简单咯!

定义指针并初始化:

struct ListNode* cur = head;
struct ListNode* next = head->next;
struct ListNode* newhead = NULL;//新链表的头

❄️头插

//头插
cur->next = newhead;
newhead = cur;

❄️ 迭代挪动

❄️终止条件

快进~

while (cur != NULL)
{
	//头插
	cur->next = newhead;
	newhead = cur;
	//迭代往后挪
	cur = next;
	if (next)
		next = next->next;
}

给出完整代码:

struct ListNode* reverseList(struct ListNode* head){
     if(head == NULL)
     {
         return head;//处理空链表
     }
     //初始化
     struct ListNode* cur = head;
     struct ListNode* next = head->next;
     struct ListNode* newhead = NULL;//新链表的头
     while(cur!=NULL)
     {
        //头插
        cur->next = newhead;
        newhead = cur;
        //迭代往后挪
        cur = next;
        if(next)
            next = next->next;
     }
     return newhead;
}

那么下面这样写也是可的,而且这里不需要再处理空链表,也无需处理next = next->next;在末尾会发生空指针的解引用问题。

这是由于迭代写法上有一点点的小改变(struct ListNode* next = cur->next;),且写在了while循环的内部。

 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;
}

本题完@边通书

以上是关于反转单链表@Leetcode--链表的主要内容,如果未能解决你的问题,请参考以下文章

看一遍就理解,图解单链表反转

Leetcode练习(Python):链表类:第206题:反转链表:反转一个单链表。

[LeetCode]反转链表

算法热门:反转单链表(LeetCode 206)解法二

leetcode之反转链表图文详解

Leetcode92. 反转链表 II