首页 > 解决方案 > 检查数组是否是单峰的

问题描述

一个整数数组是单峰的,如果:

一开始是严格增加的;之后它是恒定的;在那之后,它是严格下降的。第一个块(增加)和最后一个块(减少)可能不存在。允许这两个块都不存在。

例如下面三个数组是单峰的:[5, 7, 11, 11, 2, 1], [4, 4, 2], [7],但是下面三个不是单峰的:[5, 5, 6 , 6, 1], [1, 2, 1, 2], [4, 5, 5, 6]。

编写一个 C 程序来检查一个数组是否是单峰的。限制:函数应该按 n 的顺序运行。数组元素之间的比较操作不应超过 n-1 次。

我可以使用 3 个 while 循环(非嵌套)并检查数组的 3 个部分,如果第 1 部分增加然后第 2 部分是恒定的并且第 3 部分减少吗?

标签: carrays

解决方案


虽然可以为单峰曲线中的每个可能阶段在三个循环中对此进行编码,但这种“有状态”算法并不是特别数学。请注意,通过将状态保留在变量中而不是代码控制流中,可以在单个循环中实现等效的有状态算法。

它可能在数学上更稳健(或至少证明对这种曲线的数学理解),并且更简单地测试单个公分母 - 即对于单峰曲线上的每个点都成立的共同关系,但是不适用于任何非单峰曲线。通过这种方式,您可以在单个循环中执行算术测试,而不是通过控制流或状态转换。

在这种情况下,这个单一的公分母 - 在数学上定义曲线的一个是: 曲线梯度的符号是单调递减的

Signum 是一个函数,使得 signum(a) 是:

  • 0 如果 a == 0,
  • 1 如果 a > 0,
  • -1 如果 a < 0

虽然单调递减意味着该值要么下降要么保持不变,但永远不会上升——它都是下坡或高原。

任何一点的梯度只是 d[n+1] - d[n]。所以循环从另一个元素中减去一个元素,确定符号,并将其与前一个符号进行比较。如果符号增加,则曲线不是单峰的。那就是它只能上升,只能平坦或只能下降,或者它可以上升和下降,但永远不会再次上升,具有任意数量的水平高原。

请注意,此解决方案适用于单峰曲线的数学定义;您问题中的定义有些模棱两可,似乎不允许出现多个高原。也就是说,它允许:

   _________
  /         \
 /           \
/             \

但不包括例如:

      ___
     /   \
 ___/     \____
/              \

然而,我认为第二个显然是单峰的。

来自:https ://en.wikipedia.org/wiki/Unimodality : 在此处输入图像描述

最后一部分是关键 -零不算作符号更改。然而,无论这种微妙之处如何,它都适用于您的所有测试用例。


推荐阅读