29-出现次数超过一半的数的查找

【题目描述】

        数组中有一个数出现的次数超过了数组长度的一半,找出这个数

【解题方法】

1、若数组有序:

    方法:可直接输出数组n/2位置上的元素即可

2、若数组无序

    方法一:排序
        采用快速排序,将无序数组变成有序数组,再输出n/2位置上的元素即可,复杂度为O(nlogn);
    方法二:哈希表
        1)根据题目需求,可设计出哈希表的数据结构(两个int,其中一个存储数组中的数data,另一个存储数出现的次数count)
        2)冲突解决:根据题目需求,若出现冲突,则对应data的count++
        3)哈希函数构造:采用取余法

        哈希表的查找时间复杂度:O(1),空间复杂度为O(n)

    代码实现

/**********************************
Author:tmw
date:2018-2-25
**********************************/
#include <stdio.h>
#include <stdlib.h>

//这里定义哈希表的大小,题给测试例数组长度为5,因此设5,根据题目情境,HASHSIZE的设定值最好为给定数组长度
#define HASHSIZE 10
#define init_data -65534

/**数据结构定义**/
typedef struct hash_node
{
    int data;
    int count;
}hash_node;

/**定义哈希表**/
struct hash_node HashTable[HASHSIZE];

/**哈希表初始化**/
void init_hash_table()
{
    int i;
    for(i=0;i<HASHSIZE;i++)
    {
        HashTable[i].data = init_data;
        HashTable[i].count = 0;
    }
}

/**哈希函数的定义**/
int hash_func(int key)
{
    return key%HASHSIZE;
}

/**哈希表的建立**/
void create_hash_table(int key)
{
    int hash_index = hash_func(key);
    //当哈希表中没有key时,则将key插入表中
    if(HashTable[hash_index].data==init_data)
        HashTable[hash_index].data = key;
    //当哈希表存在key时,不需要将key插入,直接让记录key值个数的count++即可
    else
        HashTable[hash_index].count++;
}

/**在hash表中查找最大的count数,并返回对应值**/
int hash_find()
{
    hash_node p; //p的count记录最大的count值,p的data用于返回找到的值
    p = HashTable[0];
    int i;
    for(i=1;i<HASHSIZE;i++)
    {
        if(HashTable[i].count > p.count )
           p = HashTable[i];
    }
    return p.data;
}
    
方法三:记录两个值--依据题目特殊性的特殊解法
        设两个值:candidate和ctimes:其中candidate用来存储遍历数组过程中的某个数;ctimes用于记录当前数出现的次数,初始值为1
        1)如果下一个数与当前candidate数相同,则ctime++
        2)如果下一个数与当前candidate数不同,则ctimes--
        3)当ctimes为0时,则candidate数换成下一个数,同时将ctimes置1
        数组遍历完后,返回candidate数

        时间复杂度为O(n),空间复杂度为O(1)

代码实现

/********************************
Author:tmw
date:2018-2-25
*********************************/
#include <stdio.h>
#include <stdlib.h>

int Remark2number_find_key(int array[],int array_length)
{
    //初始化camdidate值为数组首元素
    int candidate = array[0];
    //初始化ctimes值为1
    int ctimes = 1;
    int i;

    //遍历数组,并标记
    for(i=1;i<array_length;i++)
    {
        //变更candidate的情况:candidate数换成下一个数,同时将ctimes置1
        if(ctimes==0)
        {
            candidate = array[i];
            ctimes = 1;
        }
        else
        {
            if( array[i] != candidate )
                ctimes--;
            else
                ctimes++;
        }
    }
    return candidate;
}

值得一提的是,方法三这种特殊解法也同样适用于解决:数组中有一个数出现的次数是数组长度的一半,找出这个数 的问题

方法三测试代码和结果如下:

int main()
{
    printf("测试代码\n");

    int array1[5] = {0,1,2,1,1};
    int array2[10] = {3,2,3,3,4,3,3,2,3,4};
    int array3[10] = {10,30,20,40,50,10,10,10,20,10};
    int array4[20] = {10,30,20,40,50,10,10,10,20,10,50,10,50,10,20,10,10,10,20,30};
    int i;

    printf("数组1为:\n");
    for(i=0;i<5;i++)
        printf("%d ",array1[i]);
    printf("\n");

    printf("数组2为:\n");
    for(i=0;i<10;i++)
        printf("%d ",array2[i]);
    printf("\n");

    printf("数组3为:\n");
    for(i=0;i<10;i++)
        printf("%d ",array3[i]);
    printf("\n");

    printf("数组4为:\n");
    for(i=0;i<20;i++)
        printf("%d ",array4[i]);
    printf("\n");

    int ans1 = Remark2number_find_key(array1,5);
    int ans2 = Remark2number_find_key(array2,10);
    int ans3 = Remark2number_find_key(array3,10);
    int ans4 = Remark2number_find_key(array4,20);

    printf("数组1中出现次数超过一半的数为:%d \n",ans1);
    printf("数组2中出现次数超过一半的数为:%d \n",ans2);
    printf("数组3中出现次数恰好为一半的数为:%d \n",ans3);
    printf("数组4中出现次数恰好为一半的数为:%d \n",ans4);

    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值