【2013统考真题】已知一个整数序列A=(ao, a1,…, an-1),其中0<ai,<n(0≤i<n).若存在ap1=ap2=…=apm=X且m >n/2(0≤p,<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。
这种题,在考场上你想破脑袋研究一个时间复杂度小于O(nlogn)的最高拿11分,我只能说你会写这道题,但你不会考试,你就是暴力直接算写出一个O(n2)的,只要对也可以拿10分,何必浪费那么多时间呢?所以我这里就提供一个暴力算法的解法,你有更好的方法可以评论区留言。
代码思路:
这个所谓的主元素,其实就是让你找在一个序列中哪个元素重复出现的次数大于数组长度的一半。
而由于主元素个数会大于序列长度的一半,所以一个序列最多有1个主元素(2个的话就超过序列长度了)。
那我们直接暴力求解,用一个count标记当前元素,遍历整个序列,找出当前元素个数,如果count>(length)/2,则输出主元素。这样循环n次,直到所有元素都遍历结束
如果都遍历完还没有找到主元素,就返回-1,查找失败。
int MainElem(Sqlist L) {//如果有主元素,返回主元素,否则返回-1
int count = 0;
int i = 0;
int j = 0;
int tmp = 0;//标记候选主元素
for (i = 0;i < L.length;i++) {
int tmp = L.data[i];
count = 0;//每次重选元素count清零
for (j = 0;j < L.length;j++) {
if (L.data[j] == tmp) {
count++;
}
}
if (count > (L.length) / 2) {
return tmp;
}
}
//到这里还没return,说明没有主元素,返回-1
return -1;
}
int main() {
Sqlist L;
InitList(&L);//初始顺序表为0,5,5,3,5,7,5,5
printf("初始顺序表为:");
print(&L);
int mainElem = MainElem(L);
if (mainElem != -1) {
printf("主元素为%d", mainElem);
}
else {
printf("该序列无主元素");
}
return 0;
}
两个测试用例:
初始顺序表为0,5,5,3,5,7,5,5
ps:顺序表定义及初始化,还有打印顺序表的函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
#define MaxSize 8//定义最大长度
int InitArr[10] = { 0,5,5,3,5,1,5,7 };
int Initarr[10] = {11,13,15,17,19};
int Initbrr[10] = {2,4,6,8,20};
typedef struct {
int data[MaxSize];//用静态的数据存放数据元素
int length;//顺序表当前长度
}Sqlist;//顺序表的类型定义
//初始化一个顺序表
void InitList(Sqlist* L)
{
for (int i = 0;i < MaxSize;i++)
{
L->data[i] = InitArr[i];//将所有数据元素设置为默认初始值
}
L->length = 8;//顺序表初始长度
}
void print(Sqlist* L)
{
for (int i = 0;i < L->length;i++)
{
printf("%d ", L->data[i]);
}
}