有人能给我一个关于如何从Codibility处理以下任务的提示吗:https://codility.com/programmers/task/hilbert_maze/
我可以通过生成迷宫并使用BFS搜索最短路径来找到最短路径,但由于最坏情况下的时间复杂性预计为O(N),我认为这不是正确的方法。BFS的时间复杂度是O(|V|+|E]),其中V是顶点的数量,E是边的数量。例如,如果N=3,我们有一个尺寸为17x17的网格,很明显,我们无法在3个步骤中找到路径。
因此,要么指示的时间复杂度是错误的,应该是M^2,要么有一个快速的技巧可以在不使用图算法的情况下简单地计算两点之间的距离。我发现了一些计算2个给定点的希尔伯特距离的算法(如果这里需要的话),它们使用比特操作等,但根本无法理解。此外,我认为这项任务的目标是自己找出如何计算距离,而不是使用现有的公式。
有没有人解决了这项任务,可以进一步帮助我?谢谢
这是我提出的解决方案:
- 每个点的位置都可以由一个象限阵列及其方向来定义(它将有N个元素)——每个元素代表上一个象限中的方向。整个迷宫具有向上的方向
- 您需要为这两个点定义此数组。例如:如果N=2,并且该点位于左下象限,则其方向将向左。我们取这个象限,旋转坐标系,使其方向相同。通过这种方式,我们定义了新系统中的下一个象限和方向对。因此,如果我们的点在左下象限,那么它的方向将是向左的,但由于这是相对于我们以前的方向(也是向左的),这将变成向上的方向
- 在这一点上,我们有所有的象限和方向,向下到包含我们的点的最小迷宫。我们需要从后面(从最小的迷宫)解决它们。每个迷宫都可以通过以下规则解决:
- 如果我们当前象限中的点位于任何极端(意味着坐标的任何分量都是象限的最低或最高),我们将其留在原来的位置,否则检查下一个点
- 如果我们的点向下或位于当前象限的中间,则我们移动到象限的最低中点(这些点与之前定义的方向相对,即:如果我们的方向向上,则我们将移动到最顶部的中点)
- 如果我们的点向上(在相对方向上),我们就必须把它移到最上面的中点
- 在存储这些移动时,我们检查两个数组中是否有属于这两个点的公共元素:
- 如果不是,我们计算两个端点之间的距离,然后将两个移动列表中的所有距离相加(在该列表中,每个距离都可以计算为坐标分量减法,即:abs(x1-x2)+abs(y1-y2))
- 如果我们有共同元素,那么我们删除之后的每一个移动,包括共同元素,并计算前面提到的距离
这种解决方案是可以优化的,它只是为了从一开始就提出想法。
编辑:以下是我在Swift3中实现的上述解决方案:https://codility.com/demo/results/training9WWFXU-EWC/