一、数组内数据无序且可以重复
本文采用一种交换的方式来求出两个数组的并集,交集和差集,这种算法运算速度较快,内存消耗空间较少,是一个值得学习的好方法,另外,作者提醒您,重要的不是算法本身,而是该算法会开拓我们的思维空间,要注意对问题的多思考。
算法概述:
两个任意元素的数组,比较出两个数组中相同的元素和不同的元素。
元素划分:
计算过程中,两个数组内部元素的划分:
算法流程:
从数组1的尚未比较的元素中拿出第一个元素array1(i),用array1(i)与array2(j)进行比较(其中j>i且j<array2的长度),可能出现下面两种情况,
1. 数组2中找到了一个与array1(i)相等的元素,则将array2(j)与array2(i)进行交换,i加一,进行下次迭代
2. 数组2直到结尾也没找到与array1(i)相等的元素,则将array1(i)与尚未进行比较的最后一个元素array1(k)进行交换,i不加一,进行下次迭代。
算法实现代码:
#include <stdio.h>
bool join(const int *arrA, const int lenA, const int *arrB, const int lenB, \
int *arrDst, int *len)
{
int i = 0, j = 0, nCount = 0;
while (i < lenA && j < lenB)
{
if (arrA[i] == arrB[j])
{
//两个相等即交集
arrDst[nCount ++] = arrA[i];
i ++;
j ++;
}
else if(arrA[i] > arrB[j])
{
//移动小的数组index
j ++;
}
else
{
//移动小的数组index
i ++;
}
}
//交集的真实数目
*len = nCount;
return true;
}
bool merge(const int *arrA, const int lenA, const int *arrB, const int lenB, \
int *arrDst, int *len)
{
int i = 0, j = 0, nCount = 0;
while (i < lenA && j < lenB)
{
if (arrA[i] < arrB[j])
{
arrDst[nCount ++] = arrA[i];
//移动小的数组index
i ++;
}
else if(arrA[i] > arrB[j])
{
arrDst[nCount ++] = arrB[j];
//移动小的数组index
j ++;
}
else
{
arrDst[nCount ++] = arrA[i];
//相等只取一个
i ++;
j ++;
}
}
while(i < lenA)
{
arrDst[nCount ++] = arrA[i ++];
}
while(j < lenB)
{
arrDst[nCount ++] = arrB[j ++];
}
//并集的真实数目
*len = nCount;
return true;
}
void print(const int *arr, const int len)
{
int i;
printf("Data : ");
for(i = 0; i < len; ++ i)
{
printf("%2d ", arr[i]);
}
printf("\n\n");
}
void main()
{
int a[] = {0,1,3,5,7,8,9,10,11};
int b[] = {1,2,3,4,5,6,7,8,9,10,13,15,19};
int sizeA = sizeof(a) / sizeof(a[0]);
int sizeB = sizeof(b) / sizeof(b[0]);
int i = 0;
int j = 0;
int len;
int *c = new int [sizeA + sizeB];
printf("数组A和B的交集:\n");
join(a, sizeA, b, sizeB, c, &len);
print(c, len);
printf("数组A和B的并集:\n");
merge(a, sizeA, b, sizeB, c, &len);
print(c, len);
delete []c;
printf("\n\n");
}
三、3个已经排序的整数数列,找到common elements。
1)三个index指向三个数列开始,比较三者的值,若相等则找到一个。若有两个元素相等且较大,则较小的一个index+;其他情况,较小的两个index++。时间复杂度O(N),N小于等于最长的数列长度。
2)先找两个数组的common element,过程和归并排序类似,然后看这个结果是否出现在数组三中即可,用二分查找。时间复杂度O(n),空间复杂度为O(1),如果是N个数组,则可以采用败者树。(新学习的,呵呵)