q141 环形链表
题解
该题目可以使用hash表,但是快慢指针解法更优。
快指针的速度是慢指针的两倍,如果快慢指针进入环形链表中,那么快慢指针必定会重合。如果快指针指向nil,表示到了链表尾,不存在环形。
func hasCycle(head *ListNode) bool {
if head == nil || head.Next == nil {
return false
}
slow, fast := head, head.Next
for slow != fast {
if fast == nil || fast.Next == nil {
return false
}
slow = slow.Next
fast = fast.Next.Next
}
return true
}
q142 环形链表ii
题解
这道题应该使用快慢指针来做,但是在做之前我们得推导一个公式出来,首先我们需要一张图:
我们设head到begin的距离为A,begin到meet的距离为B。通过环形链表i我们知道,快指针的速度是慢指针的两倍,所以快指针走过的路程也是慢指针的两倍,从开始到相遇,慢指针走的路就是A+B
,而快指针就是2A+2B
,相遇的时候,其实快指针刚好比慢指针多走了一圈,即A+B+L=2A+2B
, 所以L=A+B
。这就意味着meet到begin的距离其实也是A,我们到推导的公式就是这个。
根据这个公式,我们可以知道,当快慢指针第一次相遇,这个时候我们将慢指针放到head的位置,然后两个指针以相同的速度行走,那么它们将在begin的位置第二次相遇。
func detectCycle(head *ListNode) *ListNode {
if head == nil {
return nil
}
fast, slow := head, head
// 快指针的速度更快,所以优先判断快指针是否出界
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
// 如果快慢指针第一次相遇,就将慢指针放到开始的位置
// 因为len(起点到环形入口)等于len(相遇点到环形入口)
// 所以他们第二次相遇的位置一定在环形入口
if slow == fast {
slow = head
for slow != fast {
slow = slow.Next
fast = fast.Next
}
return slow
}
}
return nil
}
q202 快乐数
题解
采用快慢指针的解法,和上一题(环形链表)的解法一样。
func isHappy(n int) bool {
if n < 2 {
return true
}
slow, fast := n, sumOfSquares(n)
for slow != fast {
if sumOfSquares(fast) == 1 {
return true
}
slow = sumOfSquares(slow)
fast = sumOfSquares(sumOfSquares(fast))
}
return false
}
func sumOfSquares(num int) (sum int) {
for num != 0 {
sum += (num % 10) * (num % 10)
num /= 10
}
return sum
}
q287 寻找重复数
题解
由于该n+1长度的数组里面包含的都是1-n的数字,所以我们可以把这个数组看成一个链表,比如1 4 3 2 3:
会变成一个环形链表,环形链表的入口就是第一个3的位置,所以这道题就可以转化成环形链表找入口的问题,可以参考环形链表ii的解法来求解:
func findDuplicate(nums []int) int {
slow, fast := 0, 0
for slow, fast = nums[slow], nums[nums[fast]]; slow != fast; slow, fast = nums[slow], nums[nums[fast]] {
}
slow = 0
for slow != fast {
slow = nums[slow]
fast = nums[fast]
}
return slow
}
q876 链表的中间节点
题解
快指针的速度是慢指针的两倍,快指针到达链表尾时,慢指针刚好到达链表的中间节点。
func middleNode(head *ListNode) *ListNode {
slow, fast := head, head
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
return slow
}