引入

我们有二分算法,就是:

定义

二分查找(英语: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. 【NestJS系列】DI依赖注入与IOC控制反转

    前言 上篇文章我们学习了如何使用nest-cli来快速生成一个NestJS后端项目,当我们打开编辑器查看代码时,会发现整个代码风格有点类似JAVA的spring框架,并且你会发现一些service类在 ...

  2. 类WPF跨平台模仿TIM

    类WPF跨平台模仿TIM Avalonia是什么? Avalonia 是一个功能强大的框架,使开发人员能够使用 .NET 创建跨平台应用程序.它使用自己的渲染引擎来绘制UI控件,确保在各种平台上保持一 ...

  3. css美化

    编辑网页文本 span标签:能让某几个字凸显出来结构:span{color:red:}    <span>123<span> 字体样式:一般设置两个字体.如果浏览器第一个字体不 ...

  4. Nginx反向代理服务流式输出设置

    Nginx反向代理服务流式输出设置 1.问题场景 提问:为什么我部署的服务没有流式响应 最近在重构原有的GPT项目时,遇到gpt回答速度很慢的现象.在使用流式输出的接口时,接口响应速度居然还是达到了3 ...

  5. chatglm2-6b模型在9n-triton中部署并集成至langchain实践

    一.前言 近期, ChatGLM-6B 的第二代版本ChatGLM2-6B已经正式发布,引入了如下新特性: ①. 基座模型升级,性能更强大,在中文C-Eval榜单中,以51.7分位列第6: ②. 支持 ...

  6. 【译】在 Visual Studio 中处理图像变得更容易了

    任何 Web.桌面或移动开发人员都经常使用图像.你可以从 C#.HTML.XAML.CSS.C++.TypeScript 甚至代码注释中引用它们.有些图像是本地的,有些存在于线上或网络共享中,而其他图 ...

  7. WPF 自定义窗体(一)

    .Net默认的窗体样式只有四种:None.SingleBorderWindow.ThreeDBorderWindow.ToolWindow,都比较"丑".而很多时候,我们希望自定义 ...

  8. 我们能从PEP 703中学到什么

    PEP703是未来去除GIL的计划,当然现在提案还在继续修改,但大致方向确定了. 对于实现细节我没啥兴趣多说,挑几个我比较在意的点讲讲. 尽量少依赖原子操作的引用计数 没了GIL之后会出现两个以上的线 ...

  9. Nomad 系列-安装

    系列文章 Nomad 系列文章 Nomad 简介 开新坑!近期算是把自己的家庭实验室环境初步搞好了,终于可以开始进入正题研究了. 首先开始的是 HashiCorp Nomad 系列,欢迎阅读. 关于 ...

  10. 微信小程序隐私保护协议修改方法 uniapp

    微信隐私保护协议指南 一天天没事闲的   01 在manifest.json 中添加一行 "__usePrivacyCheck__" : false   02 自定义一个弹窗组件 ...