链表反转golang实现
解法一:迭代(执行用时0s,内存消耗2.5MB(81.56%))
1、 直接贴代码,看完注释还不懂你打死我!!!
func reverseList(head *ListNode) *ListNode {
//判断head是否为nil若为nil则直接返回
if head == nil {
return head
}
//使用head保存当前元素
//使用next保存下一个需要反转的元素,初始的时候为nil
//定义pre保存当前元素的前一个元素初始为nil因为head未反转时,前一个元素是nil
next := new(ListNode)
var pre *ListNode = nil
//循环链表,直至head为nil,如果head为空,则说明反转完成,返回head即可
//最终返回的pre则是最终结果
for head != nil {
//先保存next变量以免反转过后找不到了
next = head.Next
//反转。将会head.next置为前一个元素
head.Next = pre
//反转后head为next,即下一个需要反转的变量,但是pre怎么存了,下一个pre应该是上一次的head,及上一次反转的节点,所以先保存pre,再保存head
pre = head
head = next
}
return pre
}
2、 测试
package reverseList
import (
"fmt"
"testing"
)
func Test_test(t *testing.T) {
node3 := ListNode{
Next: nil,
Val: 3,
}
node2 := ListNode{
Next: &node3,
Val: 2,
}
head := ListNode{
Next: &node2,
Val: 1,
}
cur := reverseList(&head)
for cur != nil {
fmt.Println(cur.Val)
cur = cur.Next
}
}
结果
``
3
2
1
## 解法二-递归
1. 代码如下
//递归法 内存消耗太大了
//基线条件和递归条件
//编写递归函数时,必须告诉它何时停止递归。正因为如此,每个递归函数都有其两部分:基线部分和递归条件。
//递归条件指的是函数调用自己,而基线条件则指的的函数不再调用自己,从而避免形成无线循环。
func reverseList(head *ListNode) *ListNode {
//1->2->3=>1<-2<-3
//重复的部分就是把箭头反向
//如果从前逆转则next节点会找不到,所以要从后逆转,每一次退出到上一层,继续逆转上一层
//第一次逆转:1->2<-3;第二次逆转1<-2<3完成
//先找到最后一个节点,即为反转后的head
var newHead *ListNode
//head==nil是为了考虑特殊情况,传入空链表
if head ==nil || head.Next == nil {
return head
}
newHead = reverseList(head.Next)
//寻找到最后一个节点即返回,此时newhead为最后一个节点,head为最后一个节点的前一个节点
//逆转
head.Next.Next = head
//将head.Next置为nil,防止形成环
head.Next = nil
return newHead
}