合并两个排序数组而无重复项的C#算法
我需要写一个算法,将两个排序的整数数组合并成一个没有重复的数组 我设法合并了它们,但我不确定如何从最终数组中删除重复项,而且用两个数组的总和启动合并数组似乎也不正确,因为重复项的默认值为合并两个排序数组而无重复项的C#算法,c#,array-merge,C#,Array Merge,我需要写一个算法,将两个排序的整数数组合并成一个没有重复的数组 我设法合并了它们,但我不确定如何从最终数组中删除重复项,而且用两个数组的总和启动合并数组似乎也不正确,因为重复项的默认值为int public static int[] MergeArrays(int[] firstArray, int[] secondArray) { var firstArrayLength = firstArray.Length; var secondArrayLenght = secondAr
int
public static int[] MergeArrays(int[] firstArray, int[] secondArray)
{
var firstArrayLength = firstArray.Length;
var secondArrayLenght = secondArray.Length;
var mergedArray = new int[firstArrayLength + secondArrayLenght];
var i = 0;
var j = 0;
var k = 0;
while (i < firstArrayLength && j < secondArrayLenght)
{
if (firstArray[i] < secondArray[j])
{
mergedArray[k] = firstArray[i];
i++;
}
else
{
mergedArray[k] = secondArray[j];
j++;
}
k++;
}
while (i < firstArrayLength)
{
mergedArray[k++] = firstArray[i++];
}
while (j < secondArrayLenght)
{
mergedArray[k++] = secondArray[j++];
}
return mergedArray;
}
公共静态int[]mergeArray(int[]firstArray,int[]secondArray)
{
var firstArrayLength=firstArray.Length;
var secondArrayLenght=secondArray.Length;
var mergedArray=新整数[firstArrayLength+SecondArrayLength];
var i=0;
var j=0;
var k=0;
而(i
如果不使用LINQ或特定于数组的方法,您将如何做到这一点呢?您几乎做到了。合并算法的主要部分已经开始工作 你只剩下两件事要做:
k
变量中跟踪合并数组的大小,因此可以使用array.resize(ref mergedArray,k)来调整数组的大小代码>
candidate
值,我们使用该值检查将插入结果数组的值是否已经在该数组中。在返回数组之前,它还会将数组大小调整为正确的大小:
public static int[] MergeArrays(int[] firstArray, int[] secondArray)
{
var firstArrayLength = firstArray.Length;
var secondArrayLength = secondArray.Length;
var mergedArray = new int[firstArrayLength + secondArrayLength];
var i = 0;
var j = 0;
var k = 0;
int candidate;
while (i < firstArrayLength && j < secondArrayLength)
{
if (firstArray[i] < secondArray[j])
{
candidate = firstArray[i];
i++;
}
else
{
candidate = secondArray[j];
j++;
}
if (k == 0 || mergedArray[k-1] != candidate)
{
mergedArray[k] = candidate;
k++;
}
}
while (i < firstArrayLength)
{
candidate = firstArray[i++];
if (k == 0 || mergedArray[k-1] != candidate)
{
mergedArray[k] = candidate;
k++;
}
}
while (j < secondArrayLength)
{
candidate = secondArray[j++];
if (k == 0 || mergedArray[k-1] != candidate)
{
mergedArray[k] = candidate;
k++;
}
}
Array.Resize(ref mergedArray, k);
return mergedArray;
}
这或多或少与Array.Resize()
的作用相同-它创建一个正确大小的新数组,并将源数组的元素复制到其中
您可能会认为您可以使用Linq来实现这一点
var result = array1.Union(array2).ToArray();
这样做的问题是,结果没有按给定顺序排序
int[] array1 = {1, 3, 5, 7, 9};
int[] array2 = {2, 4, 6, 8, 10};
int[] merged = array1.Union(array2).ToArray();
Console.Write(string.Join(", ", merged));
输出为未排序的1,3,5,7,9,2,4,6,8,10
您必须添加一个排序步骤:
int[] merged = array1.Union(array2).OrderBy(i => i).ToArray();
但是现在我们把一个O(N)
算法变成了O(N.Log(N))
算法,因为OrderBy()
是O(N.Log(N))
。这是否真的是一个问题取决于你的情况
还请注意,在返回数组之前,也可以通过返回mergedArray.Distinct().ToArray()
,从数组中删除重复项,但这会引入不必要的额外数据副本以及添加O(N)操作。如果这是家庭作业,那可能不是导师想要的
最后,您可能会注意到有一些重复的代码检查重复的值。您可以将该代码放入本地函数中以避免重复。如果这样做,最终的方法可能会如下所示:
public static int[] MergeArrays(int[] firstArray, int[] secondArray)
{
var firstArrayLength = firstArray.Length;
var secondArrayLength = secondArray.Length;
var mergedArray = new int[firstArrayLength + secondArrayLength];
var i = 0;
var j = 0;
var k = 0;
void addIfNotDupe(int candidate) // Local function.
{
if (k != 0 && mergedArray[k - 1] == candidate)
return;
mergedArray[k++] = candidate;
}
while (i < firstArrayLength && j < secondArrayLength)
{
addIfNotDupe(firstArray[i] < secondArray[j] ? firstArray[i++] : secondArray[j++]);
}
while (i < firstArrayLength)
{
addIfNotDupe(firstArray[i++]);
}
while (j < secondArrayLength)
{
addIfNotDupe(secondArray[j++]);
}
Array.Resize(ref mergedArray, k);
return mergedArray;
}
公共静态int[]mergeArray(int[]firstArray,int[]secondArray)
{
var firstArrayLength=firstArray.Length;
var secondArrayLength=secondArray.Length;
var mergedArray=新整数[firstArrayLength+secondArrayLength];
var i=0;
var j=0;
var k=0;
void addifynotdupe(int候选)//局部函数。
{
if(k!=0&&mergedArray[k-1]==候选)
返回;
mergedArray[k++]=候选人;
}
而(i
如果它们都已排序,那么您需要做的就是检查mergedArray[k-1]
(其中k>0)是否不等于您尝试插入的值?显然,在插入新值之前,不要递增k
。因为您不知道预先有多少个重复项,所以您必须分两次执行此操作(一次计数重复项,一次合并),以便正确调整结果数组的大小,或使用列表进行输出(如果确实需要数组中的结果,则在合并后转换为数组)。或者在合并结束时调整最终数组的大小(效率较低,因为它通常会使数组过大,但除非数组很大,否则这可能不会成为问题)。我恐怕不太清楚您在这里问什么。这个问题似乎是一个家庭作业问题,因为在实际代码中处理这个问题的通常方法是使用LINQ。您所要做的就是在迭代已有的合并排序时排除新值,而这些值与您刚刚编写的相同(因为重复项必须分组在一起)。你试过了吗?你试过什么了吗?你具体需要什么帮助?@PeterDuniho“在实际代码中实现这一点的通常方法是使用LINQ”。好吧,这取决于。给定排序的输入,合并应该是O(N)
,但使用LINQ可能会使其O(N.Log(N))
,因此如果数组很大,这可能是一个问题。如果OP首先对数组进行排序
public static int[] MergeArrays(int[] firstArray, int[] secondArray)
{
var firstArrayLength = firstArray.Length;
var secondArrayLength = secondArray.Length;
var mergedArray = new int[firstArrayLength + secondArrayLength];
var i = 0;
var j = 0;
var k = 0;
void addIfNotDupe(int candidate) // Local function.
{
if (k != 0 && mergedArray[k - 1] == candidate)
return;
mergedArray[k++] = candidate;
}
while (i < firstArrayLength && j < secondArrayLength)
{
addIfNotDupe(firstArray[i] < secondArray[j] ? firstArray[i++] : secondArray[j++]);
}
while (i < firstArrayLength)
{
addIfNotDupe(firstArray[i++]);
}
while (j < secondArrayLength)
{
addIfNotDupe(secondArray[j++]);
}
Array.Resize(ref mergedArray, k);
return mergedArray;
}