快慢指针方法也被称为 Hare & Tortoise 算法,该算法会使用两个在数组(或序列/链表)中以不同速度移动的指针。
61. 旋转链表
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
题解
本题可以使用快慢指针的方法,首先快指针向后移动k个节点。
然后快,慢指针一同向后前进,直到快指针到达最后一个节点。
此时,慢指针的下一个节点,就是倒数第K个节点。
这时,快指针指向头节点,进行闭环,慢指针的下一个节点置为nil。
func rotateRight(head *ListNode, k int) *ListNode {
if head == nil || head.Next == nil || k == 0 {
return head
}
l := getLen(head)
k = k % l //整除取余,取最少步数
slow := head
fast := head
//快指针先向后移动k
for i := 0; i < l; i++ {
fast = fast.Next
}
//快慢指针同时向后
for fast.Next != nil {
fast = fast.Next
slow = slow.Next
}
//切换节点指向
fast.Next = head
head = slow.Next
slow.Next = nil
return head
}
//获取链表长度
func getLen(head *ListNode) int {
var l int
for head != nil {
head = head.Next
l++
}
return l
}
109. 有序链表转换二叉搜索树
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
题解
快慢指针是寻找链表中点的好办法。快指针的速度是慢指针的两倍。
当快指针到末尾节点的时候,慢指针就是此链表的中点。
此题目利用,寻找有序链表的中点,作为二叉树的一个节点,左右子树通过递归生成。
func sortedListToBST(head *ListNode) *TreeNode {
return buildTree(head, nil)
}
func buildTree(left, right *ListNode) *TreeNode {
if left == right {
return nil
}
//获取有序链表的中点
mid := getMid(left, right)
//中点即为该层递归二叉树的节点
root := &TreeNode{mid.Val, nil, nil}
//递归生成二叉树
root.Left = buildTree(left, mid)
root.Right = buildTree(mid.Next, right)
return root
}
func getMid(left, right *ListNode) *ListNode {
slow := left
fast := left
for fast != right && fast.Next != right {
fast = fast.Next.Next
slow = slow.Next
}
return slow
}
141. 环形链表
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
题解
快慢指针,快指针的速度是慢指针的两倍。
如果链表有环,那么快指针如果入环,那么当慢指针也入环,那么快指针迟早会追上慢指针。
func hasCycle(head *ListNode) bool {
fast, slow := head, head
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
if fast == slow {
return true
}
}
return false
}