这就是问题,我在接受采访时被问到了。
找到最小和最大数组的最佳时间复杂度是什么?
我回答:O(n)。遍历数组,跟踪到目前为止发现的最大值和最小值。非常简单直接的前进。
面试官问你可以用分而治之的方法来改善它。我说可能不是。然后谈话继续,最后我被要求实施分而治之的方法。
这是:
public class MinMaxInArray {
public static int[] findMinMax(int[] array, int i, int j){
// base cases
int arrLen = j - i + 1;
if (arrLen == 1)
return new int[]{array[i], array[j]}; //j and i are the same
if (arrLen == 2){
int min = Math.min(array[i], array[j]);
int max = Math.max(array[i], array[j])
return new int[]{min, max};
}
// actual divide and conquer
int mid = i + (j-i)/2;
int[] leftMinMax = findMinMax(array, i, mid);
int[] rightMinMax = findMinMax(array, mid+1, j);
return new int[]{ Math.min(leftMinMax[0], rightMinMax[0]), Math.max(leftMinMax[1], rightMinMax[1]) };
}
public static void main(String[] args){
int[] array = {20, 5, 7, 25, 30, 1, 9, 12};
int[] minMax= findMinMax(array, 0, array.length - 1); //minMax[0] = minimum value, minMax[1] = maximum value
System.out.println("min = " + minMax[0] + ", max = " + minMax[1] );
}
}
我确信这仍然是O(n),因为所有元素都要进行比较。但是面试官坚持认为它是O(log n),并让我考虑一下。我想了很多,我确信它是O(n)。如果我是正确的,仅仅应用分而治之并不总是会降低复杂性。
如果我理解这个算法仍然是O(n),请纠正我。
谢谢
答案 0 :(得分:7)
你是对的。除非对数组进行排序,否则您仍需要检查每一半中的每个元素(每个季度和每个八分之一重复)。
它可以是O(log N)的唯一方法是,如果您可以丢弃每个递归级别的搜索空间的一半(例如在排序列表中搜索特定值)和仅方式可能发生的是它是否已经分类。
但是,当然,min
和max
操作变为O(1),因为您只需抓取列表的第一个和最后一个元素,根本不需要搜索。
现在可能是审查员建议在将每个问题级别的不同部分耕种到不同的执行引擎方面进行分而治之,这样它们就可以并行运行。这是我可以看到它给你O(log N)的唯一另一种方式,但我看不到基于发布内容的真实证据表明情况如此,我认为它需要相当多的引擎。
答案 1 :(得分:0)
确定使用除法并克服查找最小值和最大值的时间复杂度是O(n)。
但是使用分而治之的比较数量可以在很大程度上减少,如果数据量很大,确实可以减少时间。
如果n是2的幂,那么除法和征服方法会进行3 / 2n -2比较。如果n不是2的幂,它会进行3 / 2n -2以上的比较。
答案 2 :(得分:0)
我也同意“使用分而治之寻找最小值,最大值”是 O(N)
因为在《分而治之》
划分 ---> 花费 O(n),因为它将每个段分成更小的段。
征服--->它可以是任何函数,它给出结果。所以时间复杂度将基于征服正在做什么。与合并排序一样,合并部分需要 log(n) 时间。
在这种情况下,征服是持续操作