编程的本质第二章看得也有点稀里糊涂,现在将自己的理解写出来,只是为了以后自己在回忆的时候有个学习。
第二章的主要内容将Transformation,中文意思是变换的意思。即现在有个操作F,对于变量x,F(x)就是在x上变换。如果F(x)的值域仍然在x的域中,那么这样的变换就可以持续进行。这样存在三种情况:
1. F...(F(x))一直重复下去,永远不出现重复,那么这个就是infinite。
2. F...(F(x))重复到某个点以后,返回之前路径上的某个点,那么这个形状是一个线连接一个圆。
3. F...(F(x))就是一个圆。
当路径中存在圆的时候,本章解决一个问题就是如何发现这个圆的入点(如果就是一个圆,那么任何一个点都是入点,connection point)。这个问题主要有两种解法:
1. 快慢指针的方法,如果路径中存在圆,那么用两个指针遍历这个圆,一个每次递进一步,一个每次递进两步,这样快指针会赶上慢指针,这样就证明这个链路存在环,负责快指针会先到达这个链路的终点。复杂度为O(3n)
template <typename F>
requires(Transformation (F))
Domain(F)
collision_point_nonterminating_orbit(const Domain(F)& x, F f)
{
Domain(F) slow = x;
Domain(F) fast = f(x);
while (fast != slow)
{
slow = f(slow);
fast = f(fast);
fast = f(fast);
}
return fast;
}
2. 采用hash的方法,将已经遍历过的点,进行hash存储,这样时间复杂度为O(nlogn),但是空间复杂度为O(n)。
第二种方法复杂度较低,但是存在一个缺点:实际中,可能没有足够的空间来存取这些点。如果环特别大,这个算法不是现实。这个算法的时间复杂度很好,只有O(n)。Robert Sedgewick发明一种算法,空间复杂度是M,时间复杂度是n(1+Θ(1/sqrt(M))。
算法的分析如下:每b个存到数组里,每个gb前面0~b个元素检测是否已经存在。具体的内容大家可以看看它的文章
3. 第二章中还讲解了如何找到环的入口问题。其实这个问题在《编程之美》或者《剑指offer》当中有,感兴趣的读者可以看看《编程之美》或者《剑指offer》这篇文章中的解释。
本文完