Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述:
给定一个头结点为 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 之间。
思路分析:
两次循环:
- 一次循环计算出链表的结节总数。
- 计算出中间结点位置。
- 第二次循环,到达中间结点位置时,返回对应的结点。
一次循环:
- 定义一个结点切片。
- 循环链表,计算出结点总数,并把各结点都添加到结点切片中。
- 计算出中间结点位置,然后从结点切片中找到对应结点后返回。
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 个结点,中间的大部分逻辑复用一下即可。
原来是结点,不是节点。囧!