一天一个LeetCode中等题目(快慢指针)

<code>给定一个带有头结点 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 之间。

/<code>

今天的题目只是个Easy的难度,的确也比较Easy。其实我一直在想,这个题的难度在哪里。我觉得,如果给你一个数组,找到中位数输出,应该每个人都会吧。为什么链表就不会呢?在于很多人对链表的理解不够透彻。这里我们复习下链表跟数组的一些差别。数组一般都是固定长度的,每个位置都可以直接O(1)复杂度访问,但是数组一个问题在于,插入的时候,要把后面的数据往后挪一个坑。而链表并没有下标,只有一个指向下一个元素的指针。所以想要访问第n个,只能够不停往后遍历。而链表插入的时候,就不像数组那么麻烦了,只要修改当前结点指向新结点,新结点指向原来的下一个结点即可。

让我们来找一个链表的中位数,最简单的方法。当然可以遍历链表的长度,然后再找到中位数,然后再从头开始,遍历中位数个,最后返回结果即可。当然这种写法太Low了。这种链表的题目,我们有个高大上的写法,就是使用两个指针,一个每次走两步,一个每次走一步,当走得快的走到头了,走得慢的不就刚好走到中位数了么?同样的道理,如果我们要求1/4,4/5,都可以使用类似的方法。下面是一个简单的代码展示。

快慢指针,在我们的面试中非常地常见。据另外一个例子,如果在一个链表中探测有没有存在环?在一个无环的链表中,快指针走到底了,慢指针还在路上。所以,如果存在环,那可定是快指针走不到底了,他还会在路上重新遇到慢指针。所以我们只要判断快指针能否跟慢指针相遇即可。