持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
LeetCode 75 —— 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 之间。
来源:力扣(LeetCode) 链接:leetcode.cn/problems/mi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
-
这道题考察了什么思想?你的思路是什么?
对于这道求链表中间节点题,我的第一想法就是先遍历链表,求其链表长度,然后找到中间结点的位置,然后再从头开始找到中间结点。
-
做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?
没想到这种思路居然一次成功,但是感觉这种方法不佳。需要注意的是使用math.Floor得到的数字是Floor类型,我的方法可能看起来不太好,可以尝试将float64类型的数据转换为int类型的数据。不过math.Floor的参数应该是float64类型。
-
有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?
还有一种快慢指针的方法,就是取二分之一处的结点,我们就给快指针的速度设置为慢指针的2倍,是不是取三分之一处的结点,我们将快指针的速度设置为慢指针的3倍呢?大家可以尝试一下:
/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func middleNode(head *ListNode) *ListNode { var l1 *ListNode = head var l2 *ListNode = head for(l2 != nil && l2.Next!=nil){ l1 = l1.Next l2 = l2.Next.Next } return l1 }
三、AC 代码:
/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */ func middleNode(head *ListNode) *ListNode { p := head var length float64 = 0 for p != nil{ length++ p = p.Next } middle := math.Floor(length / 2) for i:=0.0; i<middle; i++{ head = head.Next } return head }func middleNode(head *ListNode) *ListNode { p := head var length float64 = 0 for p != nil{ length++ p = p.Next } middle := int(math.Floor(length / 2)) for i:=0; i<middle; i++{ head = head.Next } return head }
四、总结:
我们可以看到,快慢指针方法,耗时为4ms,而单指针方法,耗时为0ms,仔细一想,快慢指针是遍历了两条链表,而单指针只遍历了一条半,但是这就有这么多倍的速度差距吗?有点匪夷所思,希望大佬给我指点迷津!
模板来源:
作者:掘金酱
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。