两个数组的并集
本文关键字:数组 两个 | 更新日期: 2023-09-27 18:16:53
给定两个数组
int arr1[n]
int arr2[m]
其中n>m
需要将两个数组的并集写入一个数组。
例如,如果输入数组为:
int arr1[] = {1, 3, 4, 5, 7}
int arr2[] = {2, 3, 5, 6}
然后程序应该创建新的数组Union作为{1, 2, 3, 4, 5, 6, 7}
实现可以是C#或Java。
为了解决这个问题,首先需要使用合并排序对数组进行排序然后进行联合
我看了看网,但没有找到优雅的方式。我看的每一个代码到处都是IF。
请建议什么是最快速、最优雅的方法
您正确地认为,按照Merge Sort中的方式合并两个列表是最有效的做法。这假设两个列表已经排序,如您的示例所示。以下是如何实现合并的示例:
function merge(left,right)
var list result
while length(left) > 0 or length(right) > 0
if length(left) > 0 and length(right) > 0
if first(left) ≤ first(right)
append first(left) to result
left = rest(left)
else
append first(right) to result
right = rest(right)
else if length(left) > 0
append first(left) to result
left = rest(left)
else if length(right) > 0
append first(right) to result
right = rest(right)
end while
return result
从这里开始,不要在最终输出中包含重复。
如果你正在寻找一个优雅的MergeSort,那么没有什么比递归函数更优雅了:-(
这是:
这是一种分而治之的策略。我们基本上将数组划分为较小的数组,对较小的数组进行排序,然后将它们合并回来。
public static void mergesort(int a[],int left, int right){
/*
* Time : O(n log n)
* Space : O(n)
*/
int b[] = new int[right -left+1];
domergesort(a,left,right,b);
}
public static void domergesort(int a[],int left,int right, int b[]){
if(left < right){
int mid = (left+right)/2;
domergesort(a,left,mid,b);
domergesort(a,mid+1,right,b);
merge(a,left,mid,a,mid+1,right,b);
for(int k=left;k<=right;k++)
a[k] = b[k-left];
}
}
如果也不多。。
来源:我的博客(http://cloudingitup.blogspot.com/p/reading-guide-arrays.html)
将它们合并为一个联盟:
public static void merge( int a[], int al, int ar, int b[], int bl, int br, int c[]){
// al : a's left index ar : a's right index c: merged array
int i= al;
int j = bl;
int k=0;
int prev = c[0];
while ( i<= ar && j <= br){
if (a[i] <= b[j])
if (prev != a[i]) // Too keep the union distinct
c[k++] = a[i++];
else
i++;
else
if (prev != b[j]) // Too keep the union distinct
c[k++] = b[j++];
else
j++;
prev = c[k-1];
}
while (i <= ar)
{
if (prev != a[i])
c[k++] = a[i++];
else
i++;
prev = c[k-1];
}
while (j <= br)
{
if (prev != b[j])
c[k++] = b[j++];
else
j++;
prev = c[k-1];
}
}
说明代码的驱动程序代码:
int arr1[] = {1,1, 3, 4,4,4,5, 7};
int arr2[] = {2, 3, 5, 6,6,8};
int c[] = new int[8];
merge(arr1,0,7,arr2,0,5,c);
for(int i=0;i<8;i++)
System.out.print(c[i]);
输出:12345678
public static void printUnion(int ar1[],int ar2[]) {
int m = ar1.length;
int n = ar2.length;
int i=0,j=0;
while(i<m && j<n) {
if( ar1[i] <ar2[j]) {
System.out.println(ar1[i]);
i++;
}else if(ar1[i] > ar2[j]) {
System.out.println(ar2[j]);
j++;
}else {
System.out.println(ar1[i]);
i++;
j++;
}
}
while(i < m)
System.out.println(ar1[i++]);
while(j < n)
System.out.println(ar2[j++]);
}
相同的代码将适用于变化最小的交叉口。。。。
在面试中,他们通常希望看到你解决问题,而不是使用库调用(例如arr1.union(arr2)
可能无法解决问题。(
这是我的想法,但像这样的东西应该工作,我认为是O(n^2(。它假定两个数组都已排序。
union.rb
arr1 = [0,2,4,9,11,12,13]
arr2 = [3,4,7,9,10,11]
def union(n, m)
if n.last > m.last
arr1 = n; arr2 = m
else
arr1 = m; arr2 = n
end
union_array = []
j = 0
arr1.each do |x|
while j < arr2.length && arr2[j] < x
if arr2[j] < x
union_array << arr2[j] unless arr2[j] == union_array.last
j += 1
end
end
union_array << x
end
union_array
end
puts union(arr1, arr2)
这个方法应该可以很好地工作,它将决定哪个数组更大,因此不必有定义的顺序。
Java:
public static <T> T[] combine(T[] a1, T[] a2)
{
return combine(a1, a2, a1.length + a2.length);
}
public static <T> T[] combine(T[] a1, T[] a2, int maxlength)
{
T[] front = null;
T[] back = null;
if(a1.length >= a2.length)
{
front = a1;
back = a2;
}
else
{
front = a2;
back = a1;
}
int len = front.length + back.length;
if(len > maxlength)
{
len = maxlength;
}
int n = 0;
T[] result = Arrays.copyOf(front, len);
int c = 0;
for(int i = 0;i < front.length;i++)
{
if(i < front.length && c < result.length)
{
result[c] = front[i];
c++;
}
if(i < back.length && c < result.length)
{
result[c] = back[i];
c++;
}
}
return result;
}
这显然不是最有效的方法,但它确实完全有效。它还包括一个封顶,如果你想合并它们,但只得到第一个,让我们来处理5个项目,那么你可以在方法中添加一个参数5。
实际上,你可以消除很多浪费,这里有很多乱七八糟的东西,我不在IDE,所以我不想去,我可能有不需要的东西。