FindMaxMin 同时找出最大最小值

给定长度为n的数组,找出最大数与最小数,最少需要多少次比较?

1. 顺序比较:动态维护最大最小值。先把前两个数比较一次,分别填入最大,最小值。对于剩下的n-2个数,每个数都与最大,最小值比较,共2n-4次,总共2n-3次。

2. 两两分组比较:先将数组划分成 n/2 组(对于奇数下取整,额外剩余一个数),每组比出大小;则数组最大值的候选者有 n/2 个数,最小值的候选者也同样有 n/2 个数(对于奇数,加上分组时剩下的一个,就是n/2上取整个数)。分别顺序比较,总的比较次数是 

\left \lfloor n/2 \right \rfloor + 2(\left \lceil n/2 \right \rceil - 1) = n + \left \lceil n/2 \right \rceil = \left \lceil 3n/2 \right \rceil - 2

实际上,可以证明这个值就是该问题的下界。具体来说,对于任意算法A,我们可以构造输入使得算法至少做这么多次比较。

引入“信息单元”的概念,在这个问题里(不妨假设数组中的数字各不相同),最终可以确定min与任意数比较都小,max与任意数比较都大。其余的数字比较结果则不重要。也就是一共有2(n-1)个信息单元。

算法运行时,我们给数组中的每个数都维护一个状态。N表示没有参与过比较,W表示曾经赢过(大于某个数),L表示曾经输过。那么只要得到上面的2n-2个信息单元,最后的结果一定是,最小值为L状态,最大值为W状态,其余数字同时有WL状态。

这样定义的状态只会获得而不会失去,我们就可以借助这个值来计算比较次数。具体来说,考虑一下每次比较a,b会对各自状态产生什么影响?

  • N, N --> W, L   (增加两单位)
  • W, N --> W. W/ W, L  (增加一单位)
  • L, N --> L, L / L, W       (增加一单位)
  • .......等等情况

我们希望构造最坏输入,以证明任意算法都至少比较  \left \lceil 3n/2 \right \rceil - 2 次。

我们首先需要知道,给定算法,算法产生唯一确定的操作序列。通过对比较序列中参与元素的赋值,让算法尽可能少的获得信息量。

有下面的构造策略:

 具体解释一下,举例来说,对于nums.size()=6,现有算法产生下面的比较序列:(用数组下标来表示)

0,1        0, 4        2, 3        2, 5        2, 0        1, 3        4, 5        5, 3

算法比较8次,而对于n=6,(给出的下界是7次),构造一个输入:

  • 状态为[N, N, N, N, N, N], 数组为[?, ?, ?, ?, ?, ?]
  • 第一次比较0,1 NN比较,让nums[0]>nums[1],不妨赋值成20>10,算法获得两单位信息。[W, L, N, N, N, N], [20, 10, ?, ?, ?, ?]
  • 比较0,4,WN比较,让nums[0]>nums[4]赋值成20>5,获得一单位信息。这个策略让算法获得一单位信息,而不是两单位(比如让nums[4]>nums[0]就会获得两单位)。[W, L, N, N, L, N], [20, 10, ?, ?, 5, ?]
  • 比较2, 3,NN比较,赋值成15>8,获得两单位信息。[W, L, W, L, L, N], [20, 10, 15, 8, 5, ?]
  • 比较2, 5,WN比较,赋值15>12,获得一单位信息。[W, L, W, L, L, L], [20, 10, 15, 8, 5, 12]
  • 比较2, 0,WW比较,修改25>20,获得一单位信息。[WL, L, W, L, L, L],[20, 10, 25, 8, 5, 12]。注意这里,2号元素没有输过,所以增大它不会影响之前的比较结果。
  • 比较1, 3,LL比较,不需要修改,10>8,获得一单位信息[WL, WL, W, L, L, L],[20, 10, 25, 8, 5, 12]
  • 比较4, 5,LL比较,修改5>3,获得一单位信息。同样的道理,5号元素没有赢过,可以任意减小。[WL, WL, W, L, WL, L], [20, 10, 25, 8, 5, 3]
  • 比较5, 3,LL比较,修改3>2,获得单位信息。[WL, WL, W, L, WL, WL]

那为什么这种构造方式可以保证算法至少要比较 \left \lceil 3n/2 \right \rceil - 2 次?

对于任意一个序列,其中的NN比较最多有 \left \lfloor n/2 \right \rfloor 个,由此获得至多 2\left \lfloor n/2 \right \rfloor 个信息单位。对于其他情况,每次至多获得一个单位,为了获得一共2n-2个信息单位,至少还需要比较 2n-2-2\left \lfloor n/2 \right \rfloor 次。

总共至少比较 2n-2-\left \lfloor n/2 \right \rfloor = \left \lceil 3n/2 \right \rceil - 2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值