引入

我们有二分算法,就是:

定义

二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是用来在一个有序数组中查找某一元素的算法。

过程

以在一个升序数组中查找一个数为例。

它每次考察数组当前部分的中间元素,如果中间元素刚好是要找的,就结束搜索过程;如果中间元素小于所查找的值,那么左侧的只会更小,不会有所查找的元素,只需到右侧查找;如果中间元素大于所查找的值同理,只需到左侧查找。

能不能有三分算法呢?正当我以为这是一个天才的想法时,我发现:

如果需要求出单峰函数的极值点,通常使用二分法衍生出的三分法求单峰函数的极值点。

三分法与二分法的基本思想类似,但每次操作需在当前区间 \([l,r]\)内任取两点 \(lmid,rmid(lmid < rmid)\)。如果 \(f(lmid)<f(rmid)\),则在 \([rmid,r]\)中函数必然单调递增,最小值所在点(下图中的绿点)必然不在这一区间内,可舍去这一区间。反之亦然。

以上皆来自OI-WIKI


注意,这里我指的三分并不是求单峰函数中的三分,它只能求单调函数,每次去掉三分之二的部分。

那么,既然有三分了,有没有四分、五分、六分甚至 \(k\) 分呢?\(k\) 分算法存在有意义吗(\(k>3\))?\(k\) 分算法是 \(k\) 越大越好吗?

于是,我的思索开始了。

本文仅代表个人观点,计算过程如有不严谨,希望您原谅并指出,时间复杂度忽略了部分时间,不代表最终结果。

最后 sto各位大佬

思索

\(k\) 分算法的复杂度为 \(k\log_kN\),那么我们就需要知道 \(k\) 取什么才能让它最小。

证明

下面我们证明

\[f(k)=k\log_kN
\]

在 \(k>1,N>1\) 情况下的极小值时 \(k\) 的取值。

当我们要证明一个函数的极小值时的取值时,我们可以通过求导的方式。那么我们不得不引出导数这个概念。

我懒得写,大家请看:这里

那么一句话总结,导数就是函数在某点的切线的斜率,例如下面这张图:

那么在导数函数结果等于0时,当前结果是极大值还是极小值呢?

极大值

噢,错啦

极小值

噢,错啦

其他(干脆你说你想看答案)

答对啦,正确答案是有可能是极大值也有可能是极小值(没想到吧)

往下翻

当导数函数结果等于0时,当前有可能是最大值也有可能是极小值,我们称这个点为临界点。我们可以检查临界点的邻域,即临界点的左右两侧。如果在临界点的左侧函数值递增,右侧函数值递减,则该点为最大值。如果在临界点的左侧函数值递减,右侧函数值递增,则该点为极小值

接下来,我们的问题就变成了求:

\[f'(k)=0
\]

时 \(k\) 的取值。

$f'$ 是什么

就是 $f$ 函数的导数

根据换底公式, \(\log_kN = \frac{\ln N}{\ln k}\),我们可以将 \(f(k)\) 重写为 \(f(k) = \frac{k}{\ln k} \ln N\)。

换底公式证明

要证明 $\log_kN=\frac{\log_bN}{\log_bk}$ (换底公式)
$$
\text{设} y=\log_kN
$$

\[k^y=N
\]
\[\log_bk^y=\log_bN
\]
\[y\log_bk=\log_bN
\]
\[y=\frac{\log_bN}{\log_bk}
\]

首先,可以使用乘法法则对函数 \(f(k)\) 进行求导。

根据乘法法则,若有两个函数 \(u(k)\) 和 \(v(k)\),那么:

\[(u(k)\cdot v(k))'=u'(k)\cdot v(k)+u(k)\cdot v'(k)
\]

代入它,得到:

\[f'(k) = (\frac{k}{\ln k})'\cdot(\ln N)+(\frac{k}{\ln k})\cdot(\ln N)'
\]

其中,我们知道, \(N\) 是一个常数,那么 \(\ln N\) 也是一个常数。根据导数的定义,常数的导数为0。

你要我证明?

你看,常数的斜率不就是0吗

我们现在化简后知道:

\[f'(k) = (\frac{k}{\ln k})'\cdot(\ln N)
\]

那么,\((\frac{k}{\ln k})'\) 又是多少呢?

这时,我们的任务变成了求 \((\frac{k}{\ln k})'\),可以使用除法法则进行求导。

根据除法法则,若有两个函数 \(u(k)\) 和 \(v(k)\),那么:

\[(\frac{u(k)}{v(k)})' = \frac{u'(k)\cdot v(k)-u(k)\cdot v'(k)}{v(k)^2}
\]

代入它,得到:

\[(\frac{k}{\ln k})' = \frac{k'\cdot (\ln k)-k\cdot (\ln k)'}{\ln^2 k}
\]

因为 \(k\) 是一个自变量,所以它的导数为1(可以画图看,它的斜率是不是1),同时根据导数表,我们知道 \(\ln(k)'=\frac{1}{k}\),代入得:

\[(\frac{k}{\ln k})' = \frac{\ln k-k\cdot\frac{1}{k}}{\ln^2 k} = \frac{\ln (k)-1}{\ln^2 k}
\]

再代回上面那个:

\[f'(k) = (\frac{k}{\ln k})'\cdot(\ln N) = \frac{(\ln N)(\ln (k)-1)}{\ln^2 k}
\]

求导完成,撒花!!!\(@0@)/

然后就简单了,因为

\[f'(k) = 0
\]

所以:

\[\frac{(\ln N)(\ln (k)-1)}{\ln^2 k} = 0
\]

所以:

\[(\ln N)(\ln (k)-1) = 0
\]

因为 \(N > 1\),所以 \(\ln (k)-1=0\),\(\ln k=1\)

那么 \(k\) 是几?当然是 \(k=e\) 啦!!!

大家感兴趣的还可以尝试二阶导数,然后判断二阶导数是否大于0,当二阶导数大于零时,该点为极小值点;当该点的二阶导数小于零时,该点为极大值点。(费马引理

下面补上二阶导数的计算过程:

因为 \((c\cdot u(k))'=c\cdot u'(k)\) (大家可以用乘法法则自己证一下,这里 \(c\) 为常数)

\[f''(k) = \frac{(\ln N)(\ln (k)-1)}{\ln^2 k}
\]
\[\Downarrow
\]
\[f''(k) = \ln N\cdot(\frac{\ln (k)-1}{\ln^2k})'
\]

根据除法法则:

\[\ln N\cdot (\frac{(\ln(k)-1)'\cdot\ln^2k-(\ln(k)-1)\cdot(\ln^2k)'}{\ln^4k})
\]

根据加减法则(\((u(k)-v(k))'=u'(k)-v'(k)\)):

\[\ln N\cdot\frac{((\ln k)'-(1)')\cdot\ln^2k-(\ln(k)-1)\cdot(\ln^2k)'}{\ln^4k}
\]
\[\Downarrow
\]
\[\ln N\cdot\frac{(\frac{1}{k}-0)\cdot\ln^2k-(\ln(k)-1)\cdot(\ln^2k)'}{\ln^4k}
\]

根据链式法则(设 \(y=f(u),u=g(k)\),则 \(y'(k)=f'(u)\cdot g'(k)\)),且因为 \((x^\alpha)'=\alpha x^{\alpha-1}\)

\[\ln N\cdot\frac{\frac{1}{k}\cdot\ln^2k-(\ln(k)-1)\cdot((\ln k)^2)'}{\ln^4k}
\]
\[\ln N\cdot\frac{\frac{1}{k}\cdot\ln^2k-(\ln(k)-1)\cdot((2 \ln k)\cdot(\ln k)')}{\ln^4k}
\]
\[\Downarrow
\]
\[\ln N\cdot\frac{\frac{1}{k}\cdot\ln^2k-2(\ln(k)-1)\cdot\ln k\cdot\frac{1}{k}}{\ln^4k}
\]
\[\ln N\cdot\frac{\frac{\ln^2k}{k}-\frac{2(\ln(k)-1)\cdot\ln k}{k}}{\ln^4k}
\]

我们发现,当 \(k=e\) 该二阶导数大于0,故该点为极小值点。

那么好了,当我们进行 \(e\) 分时时间复杂度最少,但是我们总不能进行 2.718 分吧?所以我们取一个整数值,2或者3。

代入后可以得到,3的斜率更小,故选择3。


upd:假的,二分更优,因为三分查询数组次数过多当数据大(10000组10000000的数据)时会慢几毫秒

k 分算法是 k 越大越好吗?的更多相关文章

  1. 从K近邻算法谈到KD树、SIFT+BBF算法

    转自 http://blog.csdn.net/v_july_v/article/details/8203674 ,感谢july的辛勤劳动 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章 ...

  2. k近邻算法

    k 近邻算法是一种基本分类与回归方法.我现在只是想讨论分类问题中的k近邻法.k近邻算法的输入为实例的特征向量,对应于特征空间的点,输出的为实例的类别.k邻近法假设给定一个训练数据集,其中实例类别已定. ...

  3. [机器学习系列] k-近邻算法(K–nearest neighbors)

    C++ with Machine Learning -K–nearest neighbors 我本想写C++与人工智能,但是转念一想,人工智能范围太大了,我根本介绍不完也没能力介绍完,所以还是取了他的 ...

  4. <转>从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

    转自 http://blog.csdn.net/likika2012/article/details/39619687 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章待写:1.KD树:2.神经 ...

  5. 从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

    转载自:http://blog.csdn.net/v_july_v/article/details/8203674/ 从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 前言 前两日,在微博上说: ...

  6. 02-16 k近邻算法

    目录 k近邻算法 一.k近邻算法学习目标 二.k近邻算法引入 三.k近邻算法详解 3.1 k近邻算法三要素 3.1.1 k值的选择 3.1.2 最近邻算法 3.1.3 距离度量的方式 3.1.4 分类 ...

  7. 1.K近邻算法

    (一)K近邻算法基础 K近邻(KNN)算法优点 思想极度简单 应用数学知识少(近乎为0) 效果好 可以解释机器学习算法使用过程中的很多细节问题 更完整的刻画机器学习应用的流程 图解K近邻算法 上图是以 ...

  8. k邻近算法(KNN)实例

    一 k近邻算法原理 k近邻算法是一种基本分类和回归方法. 原理:K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实 ...

  9. 机器学习——KNN算法(k近邻算法)

    一 KNN算法 1. KNN算法简介 KNN(K-Nearest Neighbor)工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分 ...

  10. K临近算法

    K临近算法原理 K临近算法(K-Nearest Neighbor, KNN)是最简单的监督学习分类算法之一.(有之一吗?) 对于一个应用样本点,K临近算法寻找距它最近的k个训练样本点即K个Neares ...

随机推荐

  1. zynq7000 emc启动及其加速

    背景需求 ZYNQ 7000系统在出场时需要将固件从eMMC启动,原因有2: FLASH存储空间小: SD卡容易脱落,不适合产品存放系统文件: 需要注意,ZYNQ7000 系列不支持eMMC作为BOO ...

  2. 当cmd运行python无法显示中文报错 SyntaxError: Non-UTF-8 code starting with 时

    报错图片: 解决方法: 在python的脚本开头加上 再运行后

  3. 活动回顾:Flutter实时音视频应用场景实践

    11月7日,即构和上海GDG技术社区联合举办了实时音视频技术云上技术分享专场,来自即构科技和Bilibili的资深技术专家进行了深度分享.大会吸引了500+开发人员交流.观看,并在活动过程中与分享嘉宾 ...

  4. matlab2014a破解不完全,报错Test checkout of feature 'Compiler' failed

    解决方案 报错情况: 目标是把.m文件转化为.exe文件,先运行 mcc -m 你的文件.m 如果报错 Test checkout of feature 'Compiler' failed 是因为你的 ...

  5. Istio 入门(五):访问控制和流量管理

    本教程已加入 Istio 系列:https://istio.whuanle.cn 目录 4, 流量管理 基于版本的路由配置 基于 Http header 的路由配置 故障注入 两种故障注入 比例分配流 ...

  6. Mybatis(注解CRUD)

    可以在工具类创建的时候实现自动提交事务! public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession( ...

  7. 【MAUI Blazor踩坑日记】1.关于图标的处理

    前言 本系列文章,默认你已经踏上了MAUI Blazor的贼船,并且对MAUI Blazor有了一些了解,知道MAUI是什么,知道Blazor是什么. 不会教你怎么写MAUI Blazor的项目,只是 ...

  8. Lucene.Net  -全文检索引擎

    简介 Lucene.Net只是一个全文检索开发包,不是一个成型的搜索引擎,它的功能就是负责将文本数据按照某种分词算法进行切词,分词后的结果存储在索引库中,从索引库检索数据的速度灰常快 版本使用 3.0 ...

  9. 理解TCP四次挥手

    以AB通电话举例: A的视角 A突然说,"现在几点了",进入FIN_WAIT_1 B回,"啊,10点了",A听到后不说话,进入FIN_WAIT_2 然后B说,& ...

  10. pandas 格式化日期

    output_data["ShipDate"] = output_data["ShipDate"].dt.strftime("%Y/%m/%d&quo ...