题目:
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:[3,2,3]
输出:3
示例 2:
输入:[2,2,1,1,1,2,2]
输出:2
进阶:
尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
第一种解法:go中的map,很简单
func majorityElement(nums []int) int {
numsinfo := map[int]int{}
for i := 0; i < len(nums); i++ {
numsinfo[nums[i]]++
}
ele := 0;
count := 0;
for key,value := range numsinfo {
if count < value {
ele = key
count = value
}
}
return ele
}
第二种解法:摩尔投票法
存在元素a为众数,轮询数组,假设每次众数都与非众数抵消一次,最后肯定能够剩余众数出来
int majorityElement(int* nums, int numsSize){
int ele = nums[0];
int count = 1;
for(int i = 1; i < numsSize; i++)
{
if(nums[i] == ele)
count++;
else
{
count--;
if(count < 0)
{
ele = nums[i];
count = 1;
}
}
}
return ele;
}
第三解法:C语言,根据leetcode只出现一次的数字 改写,较为复杂,使用链表统计出每一个元素出现的个数,然后轮询链表,找到统计次数大于n/2的元素
typedef struct Node{
int val;
int count;
struct Node *next;
}node;
void insert_node(node* head, node** tail, int data)
{
node * p = head->next;
while(p != *tail)
{
if(p->val == data)
{
p->count++;
return;
}
else
p = p->next;
}
node* newnode = (node *)malloc(sizeof(struct Node));
newnode->val = 0;
newnode->count = 0;
newnode->next = NULL;
(*tail)->val = data;
(*tail)->count++;
(*tail)->next = newnode;
*tail = newnode;
return;
}
int find(node* head, node *tail, int numsSize)
{
int ret;
node *p = head;
node *q = NULL;
while(p != tail)
{
if(p->count > numsSize/2)
ret = p->val;
q = p->next;
free(p);
p = q;
}
free(tail);
return ret;
}
int majorityElement(int* nums, int numsSize){
node* head = (node *)malloc(sizeof(struct Node));
head->val = 0;
head->count = 0;
node* tail = (node *)malloc(sizeof(struct Node));
head->next = tail;
tail->val = 0;
tail->count = 0;
tail->next = NULL;
int i = 0;
for(;i < numsSize; i++)
insert_node(head,&tail,nums[i]);
return find(head,tail,numsSize);
}
第四种解法:与第二种类似,写一个C语言版本的hashmap,算法还存在漏洞
优点:比较好懂,适当修改可以应对大部分元素统计算法的题目。
缺点:内存消耗较大;hash冲突采用地址链接法,算法时间复杂度不好把握;可以适当改变seed大小
typedef struct Node{
int val;
int count;
struct Node *next;
}node;
#define seed 31
node *p[seed] = {NULL};
int add_hash(int key)
{
int idx = key % seed;
idx = (idx > 0 ? idx : -idx);//负数key,防止访问数组越界
if(p[idx]->val == key)//直接找到了
{
p[idx]->count++;
return 0;
}
else if(p[idx]->val == 0 && p[idx]->count == 0)
{
p[idx]->val = key;
p[idx]->count++;
return 0;
}
else //hash冲突,地址链接法
{
node** q = &(p[idx]->next);//必须使用**,找不到时要新建node,需要修改next的值时必须使用指针的指针。
while(*q != NULL)
{
if((*q)->val == key)
{
(*q)->count++;
return 0;
}
else
*q = (*q)->next;
}
node* newp = (node*)malloc(sizeof(node));
if(newp == NULL)
{
printf("malloc err!\n");
return -1;
}
newp->count = 0;//count初始化,不然直接++会出现异常值
*q = newp;
newp->val = key;
newp->count++;
newp->next = NULL;
return 0;
}
}
int find_element(int numsSize)
{
int i = 0;
for(;i < seed; i++)
{
if(p[i]->count > numsSize/2)
{
return p[i]->val;
}
node* q = p[i]->next;
while(q != NULL)
{
if(q->count > numsSize/2)
return q->val;
q = q->next;
}
}
return 0;
}
void destroy_hash()
{
int i = 0;
for(;i < seed; i++)
{
node* q = p[i]->next;
while(q != NULL)
{
node* m = q->next;
free(q);
q = m;
}
}
}
int init_hash()
{
int i = 0;
for(; i < seed; i++)
{
p[i] = (node*)malloc(sizeof(node));
if(p[i] == NULL)
{
printf("malloc err! init hash failed!\n");
return -1;
}
p[i]->val = 0;
p[i]->count = 0;
p[i]->next = NULL;
}
return 0;
}
int majorityElement(int* nums, int numsSize){
init_hash();
for(int i = 0; i < numsSize; i++)
add_hash(nums[i]);
return find_element(numsSize);
}