求数组中差异为K的对数?

时间:2016-10-19 05:56:10

标签: c# .net algorithm linq time-complexity

基本上我正在尝试做的是

static int NumdiffExponential(int[] arr, int K)
{
    return (from i in arr
            from j in arr
            where (j - i) == K
            select 1).Count();
}

除了线性时间外,最好使用单个LINQ查询,并且采用紧凑,可读和微优的方式。所以我想出的是尝试

static int NumdiffLinear(int[] arr, int K)
{
    var counters = 
        arr
        .GroupBy(i => i)
        .ToDictionary(g => g.Key, g => g.Count());
    return 
        counters
        .Keys
        .Aggregate(
            0, 
            (total, i) => total + counters[i] * (counters.ContainsKey(K - i) ? counters[K - i] : 0)
        ); 
}

不断出现0,我无法弄清楚原因。

让我解释一下我认为它是如何运作的。如果我们有arr={1,1,1,2,3,3,5}K=2,那么counter就像

1->3, 2->1, 3->2, 5->1 

count = 0

我选择了密钥1并看到1-K=-1不是counter中的密钥,因此count =仍然是2。与密钥3相同。

对于密钥3-K=1,我们counter3中的密钥。密钥1出现counter[3]=1次出现(即2,密钥count = 3*2 = 6出现2次。因此count成对(1,3) ,(1,3),(1,3),(1,3),(1,3),(1,3),(1,3)可以形成。

通过与上面相同的逻辑,由于对(3,5),我们再向count = 7添加一个。所以答案是{{1}}。

我的算法或其实现有什么问题吗?

4 个答案:

答案 0 :(得分:5)

更具可读性和更紧凑:

static int NumdiffLinear(int[] arr, int K)
{
    return arr.SelectMany(v => arr, (a, b) => new { a, b })
                .Where(s => s.b - s.a == K)
                .Count();
}

这是一个具有相同原理的线性:

static int NumdiffLinear(int[] arr, int K)
{
    int n = 1;
    return arr.Select(value => new { value, index = n++ }) //Get number and index
                .SelectMany(indexValue => arr.Skip(indexValue.index), (a, b) => new { a = a.value, b }) //Project it with the next elements in the array
                .Where(s => s.a - s.b == K) //Do the math
                .Count();
}

答案 1 :(得分:1)

替换

(total, i) => total + counters[i] * (counters.ContainsKey(K - i) ? counters[K - i] : 0)

通过

(total, i) => total + counters[i] * (counters.ContainsKey(i-K) ? counters[i-K] : 0)

答案 2 :(得分:1)

您应该添加而不是减去。例如,您知道自己拥有Quartile3key = 1。然后你必须检查K = 2是否存在。

在您的O(n ^ 2)算法中,检查key = (1+2)。现在假设您只有J - I == KI。如果条件为真,那么简单数学只需K,那么J = K + I就应该存在。

J

答案 3 :(得分:0)

您可以按照以下方式修复您的解决方案,

public int NumdiffLinear(int[] arr, int K)
        {
            var dupsDictionary =
                arr
                    .GroupBy(i => i)
                    .ToDictionary(g => g.Key, g => g.Count());


            return dupsDictionary.Keys.Aggregate(
                0,
                (total, i) =>
                    total +
                    dupsDictionary.Keys.Where(key => i - key == K)
                        .Sum(key => dupsDictionary[key]*dupsDictionary[i]));
        }