首页 > 其他分享 >Chan's Algorithm

Chan's Algorithm

时间:2024-05-20 22:07:16浏览次数:25  
标签:log Algorithm hull 复杂度 Chan 凸包 算法 points

Chan's Algorithm

简介

以往常见的求凸包的算法复杂度多为 \(\Theta(n\log n)\)(如 Graham Scan 算法、Andrew 算法等),其中 \(n\) 是平面内的点数。

当事先已知大多数点位于凸包内部,只有少数点位于边界上时,也有更高效的算法,如 Jarvis March 算法,其复杂度为 \(\Theta(nh)\),其中 \(h\) 是凸包的顶点数。

理论上,存在 \(O(n\log h)\) 的算法,如 Kirkpatrick-Seidel 算法(Marriage-before-Conquest),但是非常复杂,不容易实现。Chan's Algorithm 结合了 Graham Scan 算法和 Jarvis March 算法,同样达到了 \(O(n\log h)\) 的复杂度,且更容易实现。

Graham Scan

简单提一下 Graham Scan 算法的流程:

  1. 选最左下角的点作为基准,因为这个点必然在凸包上
  2. 对剩下的点进行极角排序
  3. 遍历平面上所有点,将凸包视为一个单调栈,如果加入当前点的方向是逆时针的,就加入;否则不断弹出栈顶,直到新加入的点与原有的点形成的方向是逆时针的为止。
def graham_scan(points):
    n = len(points)
    if n < 3:
        return

    # Step 1: Find the point with the lowest y-coordinate (and the leftmost in case of a tie)
    p0 = min(points, key=lambda p: (p.y, p.x))
    points.remove(p0)

    # Step 2: Sort points based on the polar angle with p0
    points = sorted(points, key=cmp_to_key(lambda p1, p2: compare(p0, p1, p2)))

    # Step 3: Initialize the convex hull with the first three points
    hull = [p0, points[0], points[1]]

    # Step 4: Process the remaining points
    for p in points[2:]:
        while len(hull) > 1 and orientation(hull[-2], hull[-1], p) != 2:
            hull.pop()
        hull.append(p)

    return hull

Jarvis March

简单提一下 Jarvis March 算法的流程:

  1. 先找一个基准点,同样可以找最左下角的
  2. 从所有点中找出和凸包已有的最后一条边形成的极角最小的点(最靠近凸包外侧的点),将其加入凸包,直至凸包闭合
def jarvis_march(points):
    n = len(points)
    if n < 3:
        return

    hull = []

    # Find the leftmost point
    l = 0
    for i in range(1, n):
        if points[i].x < points[l].x:
            l = i

    p = l
    while True:
        hull.append(points[p])
        q = (p + 1) % n

        for i in range(n):
            if orientation(points[p], points[i], points[q]) == 2:
                q = i

        p = q

        if p == l:
            break

    return hull

Chan's Algorithm

假设平面上一共有 \(n\) 个不同的点,最后得到的凸包有 \(h\) 个顶点,Chan's Algorithm 的主要流程如下:

  1. 先将所有点 \(m\) 个一组,分为 \(\lceil \frac{n}{m}\rceil\) 组
  2. 对每一组使用 Graham Scan 求凸包,得到 \(\lceil \frac{n}{m}\rceil\) 个凸包,复杂度 \(O(n\log m)\)
  3. 对上一步中得到的 \(\lceil \frac{n}{m}\rceil\) 个凸包使用 Jarvis March 算法,求整体的凸包

前两步没什么可说的,算法的核心在于第三步:

注意到,使用 Jarvis March 算法求凸包的时候每次都需要找出极角最小的点。在一般的 Jarvis March 算法中,这样做是 \(O(n)\) 的。然而,由于第二步中求出的是 \(\lceil \frac{n}{m}\rceil\) 个凸包,而在凸包上求极角最小的顶点,可以二分,复杂度是 \(O(\log m)\),因此这里每次找一个点的复杂度就是 \(O(\frac{n}{m}\log m)\)。这样找到 \(h\) 个点,第三步的复杂度是 \(O(\frac{hn}{m}\log m)\)。当 \(m=h\) 的时候,总复杂度就变成了我们想要的 \(O(n\log h)\)。

此时我们就遇到了第二个问题:如果直接像 Jarvis March 算法那样找 \(h\) 次,总复杂度是 \(O(\frac{hn}{m}\log m)\),因为 \(h\) 是未知的,如果 \(m\) 的取值过小,就会退化成 \(O(nh)\),而 \(m\) 过大就会退化成 \(O(n\log n)\)。这里也不能用二分来确定 \(m\) 的值,因为当确定了二分的上界是 \(n\) 的时候,一切就全完了。此时就需要引入第二个 trick:倍增。

由于无法事先知道 \(h\) 是多少,我们干脆就假设 \(m=h\),在第三步的 Jarvis March 中,我们只找至多 \(m\) 个点,如果这些点形成的图形闭合了,那么答案自然就已经找到了;如果没有闭合,就说明 \(m\) 取小了。这样做之后,对 \(m\) 做一次尝试的复杂度就是 \(O(n\log m)\)。显然,我们可能会做很多次尝试,直到 \(m\ge h\) 为止,假设总共试了 \(k\) 次,最后整个算法的复杂度是

\[n\sum_{i=1}^{k}\log m_i \]

这个复杂度取决于 \(m_i\) 的取值策略:

若直接遍历,如 \(m_i=2,3,4,\cdots\),复杂度为 \(O(nh\log h)\)

若使用常用的倍增技术,如 \(m_i=2^1,2^2,2^3,\cdots\),复杂度为 \(O(n\log^2 h)\),此时 \(k=\lceil \log_2 h\rceil\)

这个倍增虽然没有成功将复杂度变成我们想要的样子,但它多少能给人带来一些启发:

注意到 \(2^1+2^2+\cdots +2^k=2^{k+1}-1\),如果想让这些 \(\log m_i\) 加起来是 \(O(\log h)\) 的,我们可以试着让 \(k=\log \log h\),同时 \(\log m_i=2^i\),即 \(m_i=2^{2^i}\)。

现在再来算一下复杂度:

\[n\sum_{i=1}^{\log \log h}\log 2^{2^i}\\ =n\sum_{i=1}^{\log \log h}2^i\\ <n2^{1+\log \log h}\\ =2n\log h\\ =O(n\log h) \]

后记

顺便一提,该算法也可以拓展到三维的情况。

标签:log,Algorithm,hull,复杂度,Chan,凸包,算法,points
From: https://www.cnblogs.com/theophania/p/18202911

相关文章

  • 《Object Detection Using ClusteringAlgorithm Adaptive Searching Regions in Aeria
    《ObjectDetectionUsingClusteringAlgorithmAdaptiveSearchingRegionsinAerialImages》论文10问Q1论文试图解决什么问题?小物体分布不均匀,主要问题是分辨率低、信息量小,导致特征表达能力弱;传统方法如放大图像,会增加处理时间和存储大型特征图所需的内存,图像统一均匀裁......
  • .NET 中 Channel 类(内存级消息队列)简单使用
    Channel是干什么的#TheSystem.Threading.Channelsnamespaceprovidesasetofsynchronizationdatastructuresforpassingdatabetweenproducersandconsumersasynchronously.Thelibrarytargets.NETStandardandworksonall.NETimplementations.Channelsa......
  • 518_coins_changeII_找零钱II
    问题描述链接:https://leetcode.com/problems/coin-change-ii/Youaregivenanintegerarraycoinsrepresentingcoinsofdifferentdenominationsandanintegeramountrepresentingatotalamountofmoney.'Returnthenumberofcombinationsthatmakeupthat......
  • 使用Spring HttpExchange时数据对象遇LocalDateTime字段类型json反序列化失败的解决方
    方法:重写MessageConverter,使得yyyy-MM-ddHH:mm:ss的字符串能反序列化到LocalDateTime类型上。@ConfigurationpublicclassHttpClientConfig{@Value("${service.host}")privateStringhost;@BeanRestClient.BuilderrestClientBuilder(){r......
  • 使用SaveChanges()更新数据库失败
    item.ModelType=TestCase.ModelType;item.TestType=TestCase.TestType;item.TestCaseType=TestCase.TestCaseType;item.TestCaseName=TestCase.TestCaseName;item.TestDescribe=TestCase.......
  • 322 - Coin Change 换零钱
    问题描述Youaregivenanintegerarraycoinsrepresentingcoinsofdifferentdenominationsandanintegeramountrepresentingatotalamountofmoney.Returnthefewestnumberofcoinsthatyouneedtomakeupthatamount.Ifthatamountofmoneycannotbe......
  • 【强化学习】A grid world 值迭代算法 (value iterator algorithm)
    强化学习——值迭代算法代码是在jupyternotebook环境下编写只需要numpy和matplotlib包。此代码为学习赵世钰老师强化学习课程之后,按照公式写出来的代码,对应第四章第一节valueiteratoralgorithm可以做的实验:调整gama值观察策略的变化调整惩罚值(fa)的大小观察......
  • [Algorithm] Prim's Algorithm
    Prim'salgorithmisapopularmethodusedincomputerscienceforfindingaminimumspanningtreeforaconnected,undirectedgraph.Thismeansitfindsasubsetoftheedgesthatformsatreethatincludeseveryvertex,wherethetotalweightofall......
  • Windbg的First chance exception
    什么是Firstchanceexception在Windows调试环境中,“firstchanceexception”是一个非常重要的概念,它涉及到异常处理机制的早期阶段。理解这一概念对于开发和调试程序尤为关键。以下是对"firstchanceexception"的详细解释:异常处理的两个阶段FirstChanceException:......
  • 【Halcon】示例程序学习——append_channel / tile_channels
    Name:1、append_channel——将其他矩阵(通达)附加到图像2、tile_channels——多张图像平铺成一个大图像signature:1、append_channel(MultiChannelImage,Image:ImageExtended::)2、tile_channels(Image:TiledImage:NumColumns,TileOrder:)Description:1、运算符ap......