[总结] 到底如何反转一个链表

反转链表是常见题。最基本的就是给一个链表,然后反转。如果稍微带点花样的话,LeetCode上有一些题,比如Reverse Linked List II,是叫你反转在一定范围内的nodes,比如从第二个node开始到第四个node结束,反转之间的子链表;再有比如Reverse Nodes in k-Group,是叫你每个长度为k的子链表反转。反转链表的题并没有什么高深的算法,考验的基本上就是纯粹的编程基础,链表操作。到底如何优雅地反转一个链表呢?方法可能有不止一种,这里提供一种笔者觉得比较易懂的方法。先上代码:

struct ListNode{
	int val;
	ListNode *next;
	ListNode (int v) : val(v), next(NULL) {}
};

ListNode *reverse(ListNode *head) {
	if (!head)
		return NULL;
	ListNode dummy(-1);
	dummy.next = head;
	ListNode *preM = &dummy;
	ListNode *pre = head;
	head = head->next;
	while (head) {
		pre->next = head->next;
		head->next = preM->next;
		preM->next = head;
		head = pre->next;
	}
	return dummy.next;
}

看到这里保存了几个指针:

  • preM指向的是,需要反转的部分之前的一个节点。如果是从头反转,则需要一个fakeHead;
  • pre永远都是需要翻转部分的第一个node。在整个过程中,这个指针虽然不变,但它所指向的那个node一直在向后移动,直到移动到list末尾;
  • head指向的是pre后面一个,也就是下一个需要被翻转的node。翻转的原理是,每次都把head所指向的这个node放到最前面去,然后head和pre都依次向后移动一个。
举个例子:比如我们有一个链表1---2---3,我们现在需要翻转整个链表。首先来一个fake head,链表变成了#---1---2---3,那么preM就一直指向#这个node不变;而pre永远指向1这个node不变;head一开始指向的是2。接着,把head所指向的这个node放在preM后面,链表变成了#---2---1---3,然后让head回到pre后面。于是这个时候,三个指针分别指向的是:preM: #; pre: 1; head: 3。而链表变成了: #---2---1---3。下一步链表变成了:#---3---2---1,翻转完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值