我在编程面试中遇到了这个问题,现在还不知道。
长度为n的列表,其中的元素都是没有顺序的正整数。 为了找出所有可能的三元组(a,b,c),a< b< c,列表中的c之前的b和b之前出现a。
分析算法的时间复杂度。
答案 0 :(得分:4)
没有一般算法可以比O(n ^ 3)更快,因为给定不同元素的排序输入然后输出将具有大小O(n ^ 3),因此仅产生输出将花费时间成比例。实际上,即使是随机生成的整数列表,在常数因素之前也会有n ^ 3三倍。
给定您可以简单地按列表顺序迭代所有可能的三元组,并将它们按排序顺序进行比较。这种天真的解决方案已经是渐近最好的解决方案(即O(n ^ 3))
for (int i = 0; i < n; i++)
for (int j = i+1; j < n; j++)
for (int k = j+1; k < n; k++)
if (X[i] < X[j] && X[j] < X[k)
output(X[i],X[j],X[k])
我怀疑你的问题陈述中可能有转录错误 - 否则问题应该是一个非常简单的短编码练习。
答案 1 :(得分:3)
如果已知只有一小部分三元组(比如k),那么您可能更愿意通过存储指向前一个最小元素的指针来找到所有三元组。
准备一个空的数据结构(可能的选择稍后描述)。
准备一个长度为n的空数组B.
然后对于列表中的每个元素c:
数据结构需要能够存储值,位置对,以便在值小于c的所有元素上轻松找到最大位置(即最近的位置)。
如果允许值的范围相当小,一种简单的方法是使用一系列数组,其中A [k] [x]存储[x * 2 ^ k范围内所有元素的最大位置, (X + 1)* 2 ^ k)的
如果值最多为M位(即值在0到2 ^ M-1范围内),则更新或访问此数据结构都是O(M)操作。
给定的方法是O(nM + k)。
如果值的范围较大,则可以使用二叉搜索树的形式而不是一系列数组,或者对值进行排序并将值替换为其序数值。这将具有复杂度O(nlogn + k)。
如果您只想知道此表单的三元组总数,那么您可以在O(n)中执行此操作。
这个想法与以前类似:
为了使这个O(n)我们需要能够在O(n)中找到下一个更大的元素。这可以通过以下方式完成:
我们还需要能够在O(n)中找到更多元素的数量。一旦准备好NGE阵列,我们就可以通过在阵列上向后迭代并计算
来找到计数count_greater_elements[i] = count_greater_elements[ NGE[i] ] + 1 if NGE[i] is defined
= 0 otherwise
最近的较小元素和计数可以用类似的方式计算。
答案 2 :(得分:2)
一般情况的N ^ 2解决方案(计算所有这样的三元组,不输出全部;输出将仅因为它的大小而取n ^ 3):
对于数组中的每个数字X,使用小于x的索引计算小于X的数字,使用大于X的索引计算大于X的数字。对于每个X,我们可以获得三元组的数量,其中X是中间元素就像[X] *更大[X]一样。答案是这些产品的总和。
int calc(vector<int> numbers) {
int n = numbers.size();
vector<int> less(n), more(n);
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (numbers[i] < numbers[j])
less[j]++, more[i]++;
int res = 0;
for (int i = 0; i < n; i++)
res += less[i] * more[i];
return res;
}