方法一:迭代
假设链表为 1→2→3→∅,我们想要把它改成 ∅←1←2←3。在遍历链表时,将当前节点的 next 指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用之前,还需要存储后一个节点。最后返回新的头引用。
解题思路:
1、只需要修改指针为反方向,不需要修改节点的值,就可以达到翻转链表的效果
2、需要一个cur指针指向当前节点,和一个pre指针使得当前节点指向pre,
3、一个temp来存储当前节点的下一个节点(因为headhead.Next的指针会被修改掉,要使得cur能找到下一个节点就要用temp保存起来)
4、每修改一个指针为反方向,就要更新cur指向下一个节点,和更新pre也指向下一个节点。
时间复杂度:O(n)
空间复杂度:O(1)
type ListNode struct{
Val int
Next *ListNode
}
func main(){
list:=&ListNode{}
node1:=list
node1.Val=1
node2:=&ListNode{}
node2.Val=3
node1.Next=node2
node3:=&ListNode{}
node3.Val=4
node2.Next=node3
ansNode:=reverseList(node1)
//头节点开始输出
for ansNode!=nil{
fmt.Println(ansNode.Val)
ansNode=ansNode.Next
}
}
func reverseList(head *ListNode) *ListNode {
//指向前一个节点的指针
var pre *ListNode
//指向当前节点的指针
cur:=head
for cur!=nil{
//存储当前节点的下一个节点
temp:=cur.Next
//修改指针方向
cur.Next=pre
//更新pre指针
pre=cur
//更新cur指针
cur=temp
}
//返回的是头节点
return pre
}
第二种写法:递归
递归反转思路:如果链表为空,就返回空;如果链表只有一个节点,就返回这个节点;如果有两个节点,就返回第二个节点,并将第二个节点的指针指向第一个节点,再将第一个节点的指针置为空,具体如下
使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,此后,每次函数在返回的过程中,让当前结点的下一个结点的 next 指针指向当前节点。
同时让当前结点的 next 指针指向 nil,从而实现从链表尾部开始的局部反转
当递归函数全部出栈后,链表反转完成。
type ListNode struct {
val int
Next *ListNode
}
func main() {
node1:=new(ListNode)
node1.val=1
node2:=new(ListNode)
node2.val=2
node3:=new(ListNode)
node3.val=3
node4:=new(ListNode)
node4.val=4
node1.Next=node2
node2.Next=node3
node3.Next=node4
head:=reverseList(node1)
for head!=nil{
fmt.Println(head.val)
head=head.Next
}
head=reverseList2(node1)
}
//法一:遍历链表修改指针方向
func reverseList(head *ListNode) *ListNode{
var pre *ListNode
cur:=head
for cur!=nil{
temp:=cur.Next
cur.Next=pre
pre=cur
cur=temp
}
return pre
}
//法二:递归的写法
func reverseList2(head *ListNode)*ListNode{
if head==nil{
return head
}
if head.Next==nil{
return head
}
var newNode *ListNode
newNode=reverseList(head.Next)
head.Next.Next=head
head.Next=nil
return newNode
}