题解 力扣 LeetCode 206 反转链表 C/C++ 三种思路

题目传送门:

206. 反转链表 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/reverse-linked-list/description/可以用迭代和递归来做,每种又可以具体写成不同样子,这里给出三种不同思路的代码

先说迭代:

遍历整个链表

第一个节点是将来的最后一个节点,令它指向 NULL

之后的每个节点指向之前的节点即可,每次反转前都要记录一下下一个节点

否则会和之后的节点断开联系

former 用来记录之前的节点

latter 用来在该次反转前记录下一个节点

p 不为 NULL 就继续执行,结束执行后返回 p

循环体上半部分结束后判断 latter,因为我们要返回 p 作为最后一个节点的地址

所以不能让 p == NULL

代码:

struct ListNode* reverseList(struct ListNode* head) {
    if (head == NULL) return NULL;
	struct ListNode* p = head, * latter, * former = NULL;
	while(p)
	{
		latter = p->next;
		p->next = former;
		former = p;
		if (latter == NULL) break;
		p = latter;
	}
    return p;
}

再说递归:

递归我喜欢按照这个顺序设计:

1.用非计算机语言定义函数功能

2.设计递归结束条件

3.设计除结束条件之外的条件该如何操作

此外,还有链表为空和链表只有一个节点这两种特殊情况,直接返回 head 即可

定义功能:反转 head 及其之后的所有节点,并返回新的首地址

递归结束条件:head->next == NULL,说明该节点是最后一个节点,返回该节点的地址

此外的条件该如何操作:

令此节点指向此节点的上一个节点比较难实现,难在要找到上一个节点,因为这是单向不循环链表

且题目函数只传了一个指定参数

找上一个节点麻烦但找下一个节点简单

因此我们只要在该节点的下一个节点不是最后一个节点时,令下一个节点指向该节点

也就是 (head->next)->next = head;

如果没到递归结束条件就对 head->next 继续递归

但直接这样操作又有问题

因为还没有记录该节点的下一个节点就断开了两节点的联系,这是链表比较忌讳的事

我们通过先递归,"归"之后再令 (head->next)->next = head;

就可以避免在使用下一节点的信息前丢失它

这样写还需要注意一个问题,就是要每次在反转完一次节点后

令反转前靠前的节点的->next = NULL

这是为了置空原链表头结点的->next,防止发生节点循环

去判断是否为原先的头结点比较麻烦,每次都置空就行了

代码:

struct ListNode* reverseList(struct ListNode* head) {
    if (head == NULL || head->next == NULL) return head;
    struct ListNode* memory = reverseList(head->next);
    //memory用于传递最后一个节点的地址
    (head->next)->next = head;
    head->next = NULL;//置空原链表头结点的->next,防止发生节点循环
    return memory;
}

递归还有一种更好理解 (可能吧) 的形式:

同样地,链表为空和链表只有一个节点这两种特殊情况,直接返回 head 即可

否则当前节点不动,反转之后的节点

反转之后的节点前同样记得存下一节点的地址 p,防止断开连接

反转完之后的节点之后,让 p->next 指向 head

q 用来传递并最终返回新的首地址,完成反转操作

完事了吗?提交就WA,因为存在和之前那个递归一样的情况,即节点出现循环

因为原先初始节点仍指向原先第二个节点,而反转完原先第二个节点又指向原先初始节点

我们还需要一行代码把链表结尾的 NULL 转移到原先初始节点->next:

head->next = p->next;

代码:

struct ListNode* reverseList(struct ListNode* head) {
    if (head == NULL || head->next == NULL) return head;
    struct ListNode* p = head->next;
    struct ListNode* q = reverseList(head->next);
    head->next = p->next;//把NULL从末节点->next传递到head->next
    p->next = head;
    return q;
}

你可能感兴趣的:(c++,c语言,leetcode,链表,数据结构,算法)