[LeetCode][golang] 876. 链表的中间结点

265 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述:

876. 链表的中间结点

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

示例 2:

输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])
由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。

提示:

  • 给定链表的结点数介于 1 和 100 之间。

思路分析:

两次循环:

  1. 一次循环计算出链表的结节总数。
  2. 计算出中间结点位置。
  3. 第二次循环,到达中间结点位置时,返回对应的结点。

一次循环:

  1. 定义一个结点切片。
  2. 循环链表,计算出结点总数,并把各结点都添加到结点切片中。
  3. 计算出中间结点位置,然后从结点切片中找到对应结点后返回。

AC 代码:

golang:

两次循环:

// 链表的中间结点
// 两次循环
func middleNode(head *ListNode) *ListNode {
   // 获取链表的结点总数
   node := head
   length := 1
   for ; ; length = length + 1 {
      if node.Next == nil {
         break
      }

      node = node.Next
   }

   // 中间结点位置
   iTarget := length / 2

   // 循环找到中间结点
   var result *ListNode
   node = head
   for i := 0; ; i++ {
      if i == iTarget {
         result = node
         break
      }

      node = node.Next
   }

   return result
}

单次循环:

// 链表的中间结点
// 单次循环
func middleNode(head *ListNode) *ListNode {
   // 结点指针切片,存放各结点指针
   var slice []*ListNode

   // 获取链表的结点总数并将各结点的指针保存到切片中。
   node := head
   length := 1
   for ; ; length = length + 1 {
      slice = append(slice, node)

      if node.Next == nil {
         break
      }

      node = node.Next
   }

   // 目标结点位置
   iTarget := length / 2
   
   // 从结点切片中找到对应的结点并返回
   return slice[iTarget]
}

总结:

由于已经做过了 19. 删除链表的倒数第 N 个结点,中间的大部分逻辑复用一下即可。

原来是结点,不是节点。囧!