206. 反转链表 LeetCode

问题描述

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

示例 1:

输入:head = [1,2,3,4,5]

输出:[5,4,3,2,1]

示例 2:

 


输入:head = [1,2]
输出:[2,1]


示例 3:

输入:head = []
输出:[]
 

提示:

链表中节点的数目范围是 [0, 5000]
-5000 <= Node.val <= 5000
 

进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

解题思路

迭代的方法反转链表,比较暴力的方式是不断遍历链表最后然后逐个向前,但是那样太浪费时间啦,我们可以从新链表的最后一个节点向前走。

我使用三个变量p q r,分别依次指向链表中的节点,默认情况下p节点已经是反转后的节点了,然后在while循环中只要r!=NULL,我们就一直让q也反转指向p,然后更新变量,p q r沿着原链表向右挪一个位置,然后继续。最后退出循环只需使q指向p,然后返回q即可。

递归的方法的话,使用的是从原链表的最后向前逐个连接。

设想该函数的功能是返回反转后链表的头节点,然后在该函数内对原链表head之后的节点都已反转完毕,则这就是递归函数的主要功能,然后我们只需增加细节,判断临界情况即可。

若head即为NULL,则为空链表,直接返回NULL就行。还有一个判断条件head->next==NULL,这个条件有两个作用,一是链表为单链表,二为递归的调用函数到链表最后时,由于需要返回反转后链表的头节点,所以需要返回原链表的最后一个。

然后对于当前的head节点,head->next指反转后链表的最后一个,然后再->next指向head,即可完成该节点处的反转,然后使head指向NULL,最后返回head之后已反转之后链表的头节点。

解题代码


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

///
//迭代的方法反转链表
///
struct ListNode* reverseList(struct ListNode* head) {
	struct ListNode* p = head;
	//该if是为了判断空链表的情况
	if (p == NULL) {
		return p;
	}
	struct ListNode* q = p->next;
	//该if是为了判断链表中只有一个节点的情况
	if (q == NULL) {
		return p;
	}
	p->next = NULL;
	struct ListNode* r = q->next;
	//while循环迭代的反转链表,直到r为空
	while (r != NULL) {
		q->next = p;
		p = q;
		q = r;
		r = r->next;
	}
	//r为空,只需使q指向p,此时整个链表已经反转完成,返回头节点q即可
	q->next = p;
	return q;
}

///
//递归的方法
///
struct ListNode* reverseList(struct ListNode* head) {
	if (head == NULL) {
		return NULL;
	}
	if (head->next == NULL) {
		return head;
	}

	struct ListNode* newhead = reverseList(head->next);
	head->next->next = head;
	head->next = NULL;
	return newhead;
}

猜你喜欢

转载自blog.csdn.net/linwuwu985/article/details/122541216