gpt4 book ai didi

c# - 查找已排序整数数组的交集

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:26:25 25 4
gpt4 key购买 nike

让我们有一些整数短排序数组,我们需要找到等于或大于预定义常量的交集。这是代码,它演示了我想做得更好然后我可以用文字解释它。问题是速度。我的代码运行很慢。 2000 个元素数组(在我的慢机器上)大约需要 15 秒。当然,我可以实现自己的交集方法并并行化代码,但它的改进非常有限。执行时间增长为 N^2 或类似的东西,并且对于 500k 数组来说已经需要非常非常长的时间。那么我该如何重写算法以获得更好的性能呢?我不限于 c# 语言,也许 CPU 或 GPU 对此类工作有很好的特殊说明。

Example:

Input:
1,3,7,8
2,3,8,10
3,10,11,12,13,14

minSupport = 1

Output:

1 and 2: 2, 8
1 and 3: 3
2 and 3: 3, 10

    var minSupport = 2;
var random = new Random(DateTime.Now.Millisecond);

// Numbers is each array are unique
var sortedArrays = Enumerable.Range(0,2000)
.Select(x => Enumerable.Range(0,30).Select(t => random.Next(1000)).Distinct()
.ToList()).ToList();
var result = new List<int[]>();
var resultIntersection = new List<List<int>>();

foreach (var array in sortedArrays)
{
array.Sort();
}

var sw = Stopwatch.StartNew();

//****MAIN PART*****//

for (int i = 0; i < sortedArrays.Count-1; i++)
{
for (int j = i+1; j < sortedArrays.Count; j++)
{
var intersect = sortedArrays[i].Intersect(sortedArrays[j]).ToList();
if(intersect.Count()>=minSupport)
{
result.Add( new []{i,j});
resultIntersection.Add(intersect);
}
}
}

//*****************//

sw.Stop();

Console.WriteLine(sw.Elapsed);

编辑:

现在它需要大约 9 秒,而旧算法在 2000 个元素上需要 15 秒。嗯……当然不够快。

//****MAIN PART*****//

// This number(max value which array can contains) is known
var maxValue = 1000;

var reverseIndexDict = new Dictionary<int,List<int>>();

for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}

for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}

var tempArr = new List<int>();
for (int i = 0; i < sortedArrays.Count; i++)
{
tempArr.Clear();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
tempArr.AddRange(reverseIndexDict[j]);
}

result.AddRange(tempArr.GroupBy(x => x).Where(x => x.Count()>=minSupport).Select(x => new[]{i,x.Key}).ToList());

}

result = result.Where(x => x[0]!=x[1]).ToList();


for (int i = 0; i < result.Count; i++)
{
resultIntersection.Add(sortedArrays[result[i][0]].Intersect(sortedArrays[result[i][1]]).ToList());
}



//*****************//

编辑:

一些改进。

//****MAIN PART*****//

// This number(max value which array can contains) is known
var maxValue = 1000;

var reverseIndexDict = new List<int>[maxValue];

for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}

for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}



for (int i = 0; i < sortedArrays.Count; i++)
{
var tempArr = new Dictionary<int, List<int>>();

for (int j = 0; j < sortedArrays[i].Count; j++)
{
var sortedArraysij = sortedArrays[i][j];


for (int k = 0; k < reverseIndexDict[sortedArraysij].Count; k++)
{
if(!tempArr.ContainsKey(reverseIndexDict[sortedArraysij][k]))
{
tempArr[reverseIndexDict[sortedArraysij][k]] = new[]{sortedArraysij}.ToList();
}
else
{
tempArr[reverseIndexDict[sortedArraysij][k]].Add(sortedArrays[i][j]);
}

}
}


for (int j = 0; j < reverseIndexDict.Length; j++)
{
if(reverseIndexDict[j].Count>=minSupport)
{
result.Add(new[]{i,j});
resultIntersection.Add(reverseIndexDict[j]);
}
}

}

// and here we are filtering collections

//*****************//

最佳答案

有两种解决方法:

  1. 假设您有 3 个排序数组,您必须找到它们之间的交集。遍历第一个数组并对两个数组的其余部分运行二进制搜索以查找第一个数组中的元素。如果对两个列表的相应二进制搜索给出肯定,则增加交集计数器。

    result = List
    for element in Array1:
    status1 = binarySearch(element, Array2)
    status2 = binarySearch(element, Array2)
    status = status & status
    if status == True:
    count++
    if count == MAX_INTERSECTION:
    result.append(element)
    break

    时间复杂度:N * M * Log(N),
    在哪里,
    N = 数组中的元素数
    M = 阵列数

  2. 此解决方案仅在数组中的数字为正整数时才有效。计算所有排序数组中元素总数的最大值和最小值。当它被排序时,我们可以通过调查给定的排序数组的开始和结束元素来确定它。设最大数为max,最小数为min。创建一个大小为 max - min 的数组,并用零填充它。让我们假设您有 3 个数组,现在开始遍历第一个数组并转到相应的索引并增加先前创建的数组中的值。如下所述:

    element is 5 in Array 1, the New_array[5]+=1

    遍历所有三个排序列表,并执行上述操作。最后遍历new_array,寻找等于3的值,这些索引就是交集的结果。

    时间复杂度:O(N) + O(N) + .. = O(N)
    空间复杂度:O(maximum_element - minimum_element)
    在哪里,
    N = 数组中的元素数。

关于c# - 查找已排序整数数组的交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10889479/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com