给定一个整数数组,找到int对的数量,这样对于每对a_i,a_j,它们之间的数字,即a_(i + 1)... a_(j-1)都小于或等于a_i和a_j。
显然:应该计算相邻的整数,比如a_i和a_(i + 1)。 并且很容易找到O(n ^ 2)算法。
我的问题是,是否有人有比O(n ^ 2)更好的解决方案?
答案 0 :(得分:0)
我相信我在O(nlogn)中有它。
我们不必担心相邻的对,因为它们总是n-1
;因此我们可以对它们进行折扣,只需将n-1
添加到我们的最终结果中。
给定长度为arr
的整数n
数组,创建以下数据结构:
dir
长度为n-1
的布尔值dir[i] = arr[i+1] > arr[i]
。这些是移动方向,true
正在增加,false
正在减少。toPeak
- > int,表示下降的所有toPeak.get(index)
的{{1}}返回紧接index
之前的相对最大值的索引。index
- > int,表示上升的所有toValley
的{{1}}返回紧接toValley.get(index)
之前的相对最小值的索引。然后继续算法:
index
//帐户index
,并在每个索引:
counter = n-1
代表上升i <- 0...n-1
:
i
之前的山谷索引(dir[i])
(在v
中查找)i
之前的峰值索引toValley
(查询p
)v
,查找最早,最接近的值等于或小于toPeak
,在索引arr[p...v]
处发生。arr[i]
x
counter
运行时很容易证明 - 创建每个数据结构需要(i-x)
,循环索引会导致counter
次迭代,并且每次迭代需要O(n)
时间进行二分搜索(假设{{ 1}}地图查找)。
正确性更难,而且我不确定它是如何以相同的价值观展开的。现在考虑一下。
答案 1 :(得分:0)
我会递归地解决它。我认为不可能定义复杂性。 所以让我们开始(为了简化代码,我不收集它们,只是在屏幕上打印):
void check_next(int*my_arr,int count,int cur_max)
{
int temp;
if(!count || (temp=*my_arr) < cur_max)
return;
printf("%d\n",*my_arr);
check_next(++my_arr,--count,temp);
}
void main()
{
check_next(array,sizeof(array)/sizeof(int),array[0]);
}