leetcode--多数元素即众数

leetcode 多数元素

题目:

给定一个大小为 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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值