https://github.com/lflxp/accumulation/tree/master/algorithm/reverselinkedlist

题目描述

反转一个SingListNode

示例

1
2
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

解决方案

进阶

你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package reverselinkedlist

/*
leetcode 206 反转一个SingleListNode
题目描述
反转一个SingleListNode。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
图解:
https://www.cnblogs.com/mafeng/p/7149980.html
使用3个指针遍历单链表,逐个链接点进行反转。
技巧:一个全左子树变成全右子树 划分两个空间通过指针进行节点反转链接
*/
type SingleListNode struct {
	Index int
	Next  *SingleListNode
}

// 新建一个SingleListNode
func NewList() *SingleListNode {
	n1 := new(SingleListNode)
	n1.Index = 1
	n2 := new(SingleListNode)
	n2.Index = 2
	n3 := new(SingleListNode)
	n3.Index = 3
	n4 := new(SingleListNode)
	n4.Index = 4
	n5 := new(SingleListNode)
	n5.Index = 5
	n6 := new(SingleListNode)
	n6.Index = 6
	n1.Next = n2
	n2.Next = n3
	n3.Next = n4
	n4.Next = n5
	n5.Next = n6
	return n1
}

// https://blog.csdn.net/Charliewolf/article/details/82622014
// 通过迭代方案
// 1->2->3->4->5->null
// null<-1  2->3->4->5
// null<-1<-2<-3<-4<-5
func Fun_反转单链表1(head *SingleListNode) *SingleListNode {
	if head == nil || head.Next == nil {
		return head
	}
	// 先声明两个变量
	// 前一个节点
	var pre *SingleListNode
	// 后一个节点
	var next *SingleListNode

	for head != nil {
		// 保存头节点的下一个节点
		next = head.Next
		// 将头节点指向前一个节点
		// 将链表扳断 head的Next向左指向
		head.Next = pre
		// 更新前一个节点
		pre = head
		// 更新头节点
		// head是右侧断的链表 即待反转的链表
		head = next
	}
	return pre
}

// https://studygolang.com/articles/15711
// 迭代
func Fun_反转单链表2(head *SingleListNode) *SingleListNode {
	if head == nil || head.Next == nil {
		return head
	}

	var prev *SingleListNode
	cur := head
	// 当下一个值的Next不为nil时,即没有循环到最后一个时
	for cur != nil {
		// 1. cur.Next = prev 将下一个和上一个对调
		// 2. prev = cur 将index后移一位,将当前值赋值给前一个值
		// 3. cur = cur.Next 将下一个值的链表作为当前值,达到位移到下一个位置迭代
		cur.Next, prev, cur = prev, cur, cur.Next
	}
	return prev
}

var newList *SingleListNode
var endNode *SingleListNode

// 递归方式
// 进阶:你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
// http://www.voidcn.com/article/p-kvpkwcjz-bpc.html
func Fun_递归反转单链表(head *SingleListNode) {
	if head == nil {
		return
	}

	if nil == head.Next {
		endNode = head
		newList = endNode
		return
	}

	Fun_递归反转单链表(head.Next)
	endNode.Next = head
	endNode = head
	endNode.Next = nil
}

// 思路
// 使用迭代的方式反转链表大家已经很熟了,其实利用递归调用栈的特性,我们也可以轻松做到链表反转。
// 链表反转后,原链表的最后一个结点,会变成新表的头结点。因此我们可以设递归函数总是返回当前链表的最后一个结点,这样最深的一层递归调用就是原链表的尾结点,也就是新表的头结点。此后每一次递归调用结束,调用栈都会回到原表的倒数第二个结点,也就是新表的正数第二结点。确定这些后,我们只需要把每一次递归的遍历出的当前结点按顺序保存起来就好了。
func ReverseList(node *SingleListNode) *SingleListNode {
	Fun_递归反转单链表(node)
	return newList
}