题目:
算法思路:
基本思想是归并排序的思想,细节上有差异。
在进行两个有序数组合并的时候,查找重复的字符,如果重复,其中一个指针移动,一个数只存一次,由于数组的长度发生了变化 ,需要返回删除重复字符后的数组最右边界,数组在合并时只对左右边界内的数据进行处理 。
时间复杂度O(nlogn)
int remove(int a[], int b[], int l, int lm, int rm, int r) //l前半段的左边界,lm前半段的右边界 ,
{ //rm后半段的左边界,r后半段的右边界
int i = l;
int j = rm;
int k = l;
while (i <= lm && j <= r) //在数组范围内
{
if (a[i] < a[j])
{
b[k++] = a[i++];
}
else if (a[i] > a[j])
{
b[k++] = a[j++];
}
else
{
j++; //相等时,只移动指针不存储
}
}
while (i <= lm)
{
b[k++] = a[i++]; //存储剩下的数
}
while (j <= r)
{
b[k++] = a[j++]; //存储剩下的数
}
for (i = l; i < k; i++) //数组复制
{
a[i] = b[i];
}
return k - 1; //返回合并后的右边界
}
int removeall(int a[], int b[], int l, int r) //划分->递归->合并
{
int m = l + (r - l) / 2;
if (l < r)
{
int lm = removeall(a, b, l, m); //得到前半段的右边界
r = removeall(a, b, m + 1, r); //得到后半段的右边界
r = remove(a, b, l, lm, m + 1, r); //合并前后两段
}
return r;
}
int main()
{
int a[] = {1, 2, 3, 4, 5, 1, 3, 5, 7, 9};
int b[12];
int r = removeall(a, b, 0, 9);
for (int i = 0; i <= r; i++)
{
cout << a[i] << ' ';
}
return 0;
}
方法一 (分治法):
类似于归并排序的递归方法,但在combine阶段合并两个有序子序列的merge操作中,同时还删除重复的元素,即对分别位于两个子序列中相等的元素只保留一个。Merge算法的时间复杂度仍为O(n)。算法的总体复杂度为O(nlogn)。
方法二:
首先采用一个O(nlogn)复杂度的排序算法对数组进行排序;然后在数组元素有序的基础上,可以使用一个O(n)复杂度的算法删除数组中的重复元素。算法的总体复杂度为O(nlogn)。