解决此问题的最佳方法是什么? N元素阵列A的平衡点是索引i,使得较低索引上的所有元素具有值<= A [i]并且较高索引上的所有元素具有高于或等于A [i]的值。
例如,给定:
A [0] = 4 A [1] = 2 A [2] = 7 A [3] = 11 A [4] = 9
正确的解决方案之一是:2。A [2]以下的所有元素都小于A [2],A [2]之后的所有元素都大于A [2]。 在我看来,一个解决方案是O(nsquare)解决方案。有没有更好的解决方案?
答案 0 :(得分:5)
首先假设A[0]
是极点。然后开始走阵列;将每个元素A[i]
依次与A[0]
进行比较,并跟踪当前的最大值。
一旦找到i
A[i] < A[0]
A[0]
,就会知道A[i]
不再是一个极点,并且通过扩展,任何元素都不能和包括int i_pole = 0;
int i_max = 0;
bool have_pole = true;
for (int i = 1; i < N; i++)
{
if (A[i] < A[i_pole])
{
have_pole = false;
}
if (A[i] > A[i_max])
{
i_max = i;
if (!have_pole)
{
i_pole = i;
}
have_pole = true;
}
}
。所以现在继续走,直到找到比当前最大值更大的下一个值。这就成了新提出的极点。
因此, O(n)解决方案!
在代码中:
{{1}}
答案 1 :(得分:3)
如果你想知道所有极点在哪里, O(n log n)解决方案就是创建一个数组的排序副本,并查看你得到匹配值的位置。
编辑:对不起,但这实际上并不奏效。一个反例是[2, 5, 3, 1, 4]
。
答案 2 :(得分:1)
创建两个辅助数组,每个数组包含与输入数组一样多的元素,称为MIN和MAX。 MAX的每个元素M包含0..M输入中所有元素的最大值。 MIN的每个元素M包含M..N-1输入中所有元素的最小值。
对于输入数组的每个元素M,将其值与MIN和MAX中的相应值进行比较。如果INPUT [M] == MIN [M]和INPUT [M] == MAX [M]则M是一个平衡点。
构建MIN需要N步,MAX也是如此。然后测试阵列需要N个步骤。该解决方案具有O(N)复杂度并且找到所有平衡点。在排序输入的情况下,每个元素都是一个平衡点。
答案 3 :(得分:0)
创建一个双链表,例如此列表的第i个节点包含A[i]
和i
。元素增长时遍历此列表(计算这些元素的最大值)。如果某些A[bad] < maxSoFar
它不能成为MP。删除它并向后移除元素,直到找到A[good] < A[bad]
或到达列表的头部。继续(以maxSoFar
作为最大值开始),直到您到达列表的末尾。结果列表中的每个元素都是MP,每个MP都在此列表中。复杂性是 O(n),因为对于降序数组执行最多步骤 - n
前进和n
删除。
更新
哦,我在问题定义中把“任何”与“每个”混淆了:)。
答案 4 :(得分:0)
你可以结合bmcnett和Oli的答案,尽快找到所有的极点。
std::vector<int> i_poles;
i_poles.push_back(0);
int i_max = 0;
for (int i = 1; i < N; i++)
{
while (!i_poles.empty() && A[i] < A[i_poles.back()])
{
i_poles.pop_back();
}
if (A[i] >= A[i_max])
{
i_poles.push_back(i);
}
}
如果您想避免重新分配,可以使用预先分配为N的数组。