Leetcode-快慢指针遍历


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
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值