题目一
已知一个整数数列A={a0,a1,a2,…,an-1},其中0<=ai<n(0<=i<n)。若存在ap1=ap2=ap3=…=apm=x且m>n/2(0<=pk<n,1<=k<=m),则成x为A的主元素。例如A={0,5,5,3,5,7,5,5},则5为主元素;又如A={0,5,5,3,5,1,5,7},则A中没有主元素。假设A中的n个元素保存在一维数组中,请设计一个尽可能高效的算法,找出数组A的主元素。若存在主元素,则输出主元素;否则,输出-1。要求:
- 给出算法的基本设计思想。
- 根据设计思想,用C/C++实现算法。
- 说明所设计的算法的时间复杂度和空间复杂度。
基本设计思想
思路一
- 由题目可知,主要要求找出数组中重复值最多的元素并判断它是否为主元素。
- 因此,我们可以考虑先利用二路归并排序算法将数组变为有序。
- 接下来,再利用双指针i,j用于记录数组中相同值元素的个数,用变量count记录最大个数,变量mainElem记录主元素值。
- 结束数组遍历后,将count值与数组长度/2相比。若大于数组长度/2,则返回mainElem;否则,返回-1。
思路二
- 我们可以考虑计数排序的思想,利用一个辅助容器map记录arr中各元素值以及出现的个数。
- 然后,找出辅助数组中值最大的元素并判断是否符合主元素要求。即可完成题目要求。
代码实现
只实现算法二的代码
int LinearList::Question_12()
{
if(arr.length <= 1)
return arr.data[0];
map<int,int> mapp; //设置map容器用于存储arr数组中的所有元素值和对应的元素个数
mapp[arr.data[0]] = 1;
for(int i = 1;i < arr.length;i ++)
{
int value = arr.data[i];
if(mapp.count(value))
mapp[value]++;
else
mapp[value] = 1;
}
int maxCount = -1,maxElem = 0;
for(auto &pair : mapp) //遍历map,找出重复次数最多的元素
{
if(pair.second >= maxCount)
{
maxElem = pair.first;
maxCount = pair.second;
}
}
if(maxCount > arr.length/2) //判断是否符合主元素条件
return maxElem;
else
return -1;
}
效果
题目二
给定一个含n(n>=1)个整数的数组,请设计一个在时间上尽可能高效的算法,找出数组中未出现的最小正整数。例如,数组{-5,3,2,3}中未出现的最小正整数是1;数组{1,2,3}中未出现的最小正整数是4。要求:
- 给出算法的基本设计思想。
- 根据设计思想,用C/C++实现算法。
- 说明所设计的算法的时间复杂度和空间复杂度。
基本设计思想
- 根据题目要求,需找出大于0且不存在数组中的最小正整数。我们最先考虑的是,将大于0的整数升序代入数组中依次查找,找到不存在的第一个正整数即为所求。但是此算法时间复杂度度达到O(n^2),不是最理想的算法。
- 因此,我们可以考虑先利用快速排序算法是数组递增有序。再设置一个整数变量num用于和数组元素比较。若num大于等于数组元素,则说明数组中已存在该正整数,需要将num++,在与数组下一个元素比较。若num大于数组元素,则说明数组中存在重复元素,应将num与下一数组元素比较。若num小于数组元素,则该元素即为数组中不存在的最小正整数。
代码实现
Array LinearList::QuickSort(int left,int right)//快排
{
// 定义左右指针、中轴值和临时变量
int i = left, j = right;
int pivot = arr.data[(left + right) / 2];
int tmp;
// 分区操作
while (i <= j)
{
while (arr.data[i] < pivot)
i++;
while (arr.data[j] > pivot)
j--;
if (i <= j) {
// 交换 arr[i] 和 arr[j] 的值
tmp = arr.data[i];
arr.data[i] = arr.data[j];
arr.data[j] = tmp;
i++;
j--;
}
}
// 递归调用
if (left < j)
QuickSort(left, j);
if (i < right)
QuickSort(i, right);
return arr;
}
int LinearList::Question_13()
{
if(arr.length <= 0)
return -1;
QuickSort(0,arr.length-1); //执行快速排序
cout<<"Quick sorting ..."<<endl;
PrintLinearList();
int num = 1; //最小正整数变量
for(int i = 0;i < arr.length;i ++)
{
if(arr.data[i] == num)
num ++; //更新最小正整数
else if(arr.data[i] > num)
return num; //num即为所求的最小正整数
}
}