我在Codility中遇到了这个问题。参见此link。我设法解决了这个问题。但是,这给我留下了一个问题。
这是使用三个for
的代码。
public int solution(int[] A) {
Arrays.sort(A);
int k, count = 0;
for (int i = 0; i < A.length - 2; i++){
for (int j = i + 1; j < A.length - 1; j++){
for (k = j + 1; k < A.length; k++){
if (A[i] + A[j] > A[k]) break;
count += k - j - 1;
}
}
return count;
}
这是在最里面的while
中使用for
的代码。
public int solution(int[] A) {
// write your code in Java SE 8
Arrays.sort(A);
int k, count = 0;
for (int i = 0; i < A.length - 2; i++){
k = i + 2;
for (int j = i + 1; j < A.length; j++){
while (k < A.length && A[i] + A[j] > A[k]) {
k++;
}
count += k - j - 1;
}
}
return count;
}
上面的第一个解决方案在Codility方面得分不高,因为在大型测试用例中编译需要花费大量时间。但是,在第二个使用while
的解决方案中,我得到了满分。即使我在上面的两个代码中都进行了三角形检查,为什么仍会如此呢? for
和while
与这些有关系吗?
我也从第二个解决方案中了解了时间复杂度。这是link。 k
变量的初始化方式有所不同。这种差异是否会对这两个代码的性能产生巨大影响?
我正试图弄清楚这两个代码之间有什么区别。
答案 0 :(得分:1)
for loop
和while loop
与上述解决方案无关。实际上,我们可以修改第二个解决方案以使while
循环为for
循环,如下所示:
public int solution(int[] A) {
Arrays.sort(A);
int k, count = 0;
for (int i = 0; i < A.length - 2; i++) {
k = i + 2;
for (int j = i + 1; j < A.length; j++) {
for( ; k < A.length; k++) {
if ( (A[i] + A[j]) <= A[k]) break;
}
count += k - j - 1;
}
}
return count;
}
实际上,两种解决方案的主要逻辑完全不同。
第一个解决方案:
我们将使用三个for循环来修复每个可能的三元组,并在前两个最小长度对的总和小于或等于第三个最小对时即断开"if (A[i] + A[j] <= A[k]) break;"
,然后中断第三个循环。因此,整体时间复杂度将为O(n^3)
。
第二种解决方案:
我们仅修复两个for loops
并执行计算。代码中的while循环使用for loop
对于每个i
仅运行一次。由于数组已排序一次,因此该解决方案的思想是,如果我们使用前两个for loops
配对两个值,并且索引i
和j
上的值之和为{{1 }}即sum
,如果它在索引sum = A[i] + A[j]
处遇到一个大于或等于k
的值,则对于下一个对sum
和i
,第三索引肯定会大于先前的j + 1
,因为索引k
的值大于索引j + 1
即j
的值。因此,第三个索引应该绝对在上一个A[j] <= A[j + 1]
的右边。因此,第二个解决方案的总体复杂度为k
。
答案 1 :(得分:0)
在第二种解决方案中,k永远不会在第二层循环中减小。
因此,第一个解决方案的时间复杂度为O(n ^ 3),而第二个解决方案的时间复杂度为O(n ^ 2),