高频算法面试题(一)- 反转链表

578 阅读1分钟

「这是我参与11月更文挑战的第 1 天,活动详情查看:2021最后一次更文挑战

反转链表

题目来源:LeetCode-206. 反转链表

题目描述

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

示例

示例 1

image.png

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

示例 2

image.png

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

示例 3

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

提示:

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

解题

解法一:就地反转

思路

就地反转法,找一个空的节点来充当新的头结点(类似哨兵),然后遍历待反转的链表中每一个结点,将每一次遍历到的结点都插入到新的头结点后边,过程如下:

image.png

最主要的地方在于每次将遍历到的结点,插入到哨兵结点的后边

代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    if head == nil  || head.Next == nil{
        return head
    }

    newHead := &ListNode{}
    newHead.Next = head
    prevNode := newHead.Next
    currentNode := prevNode.Next
    for currentNode != nil {
        prevNode.Next = currentNode.Next
        currentNode.Next = newHead.Next
        newHead.Next = currentNode
        currentNode = prevNode.Next
    }
    head = newHead.Next

    return head
}

执行结果

image.png

解法二:头插法

思路

这种方法比较简单,就是创建一个新的链表,将待反转的链表的每一个节点,通过头插法的方式,插入到新的链表中

image.png

代码

func (list *List) ReverseListHead() {
 if list.headNode == nil {
  fmt.Println("链表为空")
  return
 }

 newList := &List{}
 currentNode := list.headNode
 nextNode := currentNode.Next
 for currentNode!=nil {
  if newList.headNode == nil {
   newList.headNode = currentNode
   newList.headNode.Next = nil
   currentNode = nextNode
   continue
  }
  nextNode = currentNode.Next
  currentNode.Next = newList.headNode
  newList.headNode = currentNode
  currentNode = nextNode
 }

 fmt.Println("反转后")
 newList.Traverse()
}