Algorithm 阵列中每对的优化算法

Algorithm 阵列中每对的优化算法,algorithm,optimization,Algorithm,Optimization,对于一个简单的算法挑战,我必须制定一个算法来解决这个问题: 给您一个由n个整数组成的数组,a0,a1,…,an-1和一个正整数k。查找并打印(i,j)对的数量,其中i=j的那些)都有可能被k整除,所以我必须迭代所有的对 那么,有什么方法可以优化我的算法吗?您可以遍历数组一次,并跟踪每个余数最多为k-1的元素数,当它们除以k时。这需要O(k)空间,但允许您在O(n+k)步骤中解决问题,如果k较小,效果会更好 伪代码(又名JavaScript): 请注意,循环中的特殊情况仅发生在最后一次迭代中,并且

对于一个简单的算法挑战,我必须制定一个算法来解决这个问题:

给您一个由n个整数组成的数组,a0,a1,…,an-1和一个正整数k。查找并打印(i,j)对的数量,其中i 最明显的暴力算法是O(n2)时间和O(1)空间(我想)。伪代码:

int count;
for each (i in array) {
    for each (j in array) {
        if (i >= j)
            continue;

        if ((i + j) % k == 0)
            count = count + 1;
    }
}
我不认为有一种方法(可能有:)-不在数组中迭代2次来计算每一对,因为每一对(当然,除了
I>=j
的那些)都有可能被k整除,所以我必须迭代所有的对


那么,有什么方法可以优化我的算法吗?

您可以遍历数组一次,并跟踪每个余数最多为
k-1
的元素数,当它们除以
k
时。这需要
O(k)
空间,但允许您在
O(n+k)
步骤中解决问题,如果
k
较小,效果会更好

伪代码(又名JavaScript):


请注意,循环中的特殊情况仅发生在最后一次迭代中,并且仅当
k
为偶数时发生,例如,如果
k
为4,那么当
i=2
时,
i==(k-i)
,因此如果没有特殊处理,我们将计算额外的元素。例如,对于示例输出,我使用了
4的
k
,有两个元素剩余
2
[2,6]
。如果我们没有额外的处理,它会说有四种方法来配对它们,相当于
(2,2),(2,6),(6,2),(6,6)
,但是额外的逻辑减去它们与自身配对的情况,因此我们剩下
(2,6),(6,2)
,然后除以2减去
i>j的情况,所以你只剩下一对被计算:
(2,6)

是的,你可以检查它@levi我想它和我的问题陈述有点不同。这里是另一个答案@levi Nice find,我提出了与答案完全相同的算法,所以我最好还是支持他的答案,哈哈。谢谢:)你是否介意添加评论或类似的内容,因为我不完全理解第二个循环是如何工作的。@raket1111当然这是有道理的。非常感谢:)
function countDivisiblePairs( arr, k ) {
    const remainders = Array( k ).fill( 0 );
    for ( let i = 0; i < arr.length; i++ ) {
        remainders[ arr[ i ] % k ]++; 
    }

    // Count the pairs of elements that were individually 
    // divisible by `k` (had a remainder of `0`), so 
    // added together they are still divisible by k
    //
    // `remainders[ 0 ]*remainders[ 0 ]` of them if we wanted all, but 
    // since we only want to count when i < j, so we subtract 
    // `remainders[0]` to get rid of the cases where `i = j` and then 
    // we divide by 2 to remove the cases where `i > j`.

    let numPairs = (remainders[ 0 ]*remainders[ 0 ] - remainders[ 0 ])/2;

    // Count the cases where the remainder wasn't 0,
    // if the remainders sum to `k`, then the sum is divisible by `k`.
    for ( let i = 1; i <= k/2; i++ ) {

        // Note that i + (k - i) = k, so each elements with a 
        // remainder of `i` can be paired with each element with
        // a remainder of `k`, but, if `k` was even there will be a 
        // final iteration where `i = (k - i)`, so we need to add a 
        // special case to only count when `i < j`, we do it the same 
        // way as we did for the case when the remainder was 0. with 
        // the if statement `(2*i === k)` is another way of writing
        // the expression `i === (k - i)`.

        if ( 2*i === k ) 
            numPairs += (remainders[ i ]*remainders[ i ] - remainders[ i ])/2;
        else
            numPairs += remainders[ i ]*remainders[ k - i ];
    }
    return numPairs;
}
countDivisiblePairs( [1,2,3,4,5,6,7,8], 2 ); // 12
countDivisiblePairs( [1,2,3,4,5,6,7,8], 3 ); // 10
countDivisiblePairs( [1,2,3,4,5,6,7,8], 4 ); // 6
countDivisiblePairs( [1,2,3,4,5,6,7,8], 5 ); // 6