考察的是查找

题干中要求:
1:在一行中给出聊天狂人的手机号码及其通话次数,其间以空格分隔。

2:如果这样的人不唯一,则输出狂人中最小的号码及其通话次数,并且附加给出并列狂人的人数。

使用哈希表解决该问题
但是要注意哈希表的性能在很大程度上是取决于散列函数的效能的

下面的方法中使用了一个非常普通但常用的散列函数,即对key取余

//散列函数
unsigned long hash(const char*str){
    unsigned long hash_value = 0;
    while(*str != '\0'){
        //直接将号码字符串逐位相加
        hash_value += *(str++);
    }
    return hash_value % MAX;
}

运行结果
 

此题满分为25分,但前两个测试用例通过仅拿到了15分 

需要选择一个更好的散列函数

DJB2算法
这里写得不标准,这是另一种等效的写法。具体的原理可以参见这里:
djb2:一个产生简单的随机分布的哈希函数

//散列函数
unsigned long hash(const char*str){
    unsigned long hash_value = 5381;
    int c;
    while((c = *(str++))){
        hash_value = (hash_value * 33) + c;
    }
    return hash_value % MAX;
}

题解如下:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define MAX 100003


//使用哈希表完成查找任务
//拉链法解决同义词冲突问题,故使用链式结构

//结点的结构体定义
typedef struct{
    char number[12];
    int count;
    struct Node* next;
}Node;

//哈希表
Node *hashTable[MAX] = {NULL};

//散列函数
unsigned long hash(const char*str){
    unsigned long hash_value = 5381;
    int c;
    while((c = *(str++))){
        hash_value = (hash_value * 33) + c;
    }
    return hash_value % MAX;
}


//核心函数
//根据输入的通话记录更新哈希表中电话号码的计数

void updateCount(const char*str){
    unsigned long hash_value = hash(str);
    //根据哈希值映射到哈希表中的指定位置
    Node *current = hashTable[hash_value];
    while(current != NULL){
        //查找应该插入的位置
        if(strcmp(current->number,str) == 0){
            current->count ++;
            return;
        }
        current = current->next;
    }
    //创建新结点,放在链首位置
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->count = 1;
    strcpy(newNode->number,str);
    newNode->next = hashTable[hash_value];
    hashTable[hash_value] = newNode;
}


int main(){
    int N;
    scanf("%d",&N);
    for(int i = 0; i < N; i ++){
        char a[12],b[12];
        scanf("%s %s",a,b);
        updateCount(a);
        updateCount(b);
    }
    //找出电话狂人
    char res_number[12] = "";
    int max_call = 0, creazyman = 0;
    for(int i = 0; i < MAX; i++){
        Node* current = hashTable[i];
        while(current != NULL){
            if(current->count > max_call){
                max_call = current->count;
                strcpy(res_number,current->number);
                creazyman = 1;
            }else if(current->count == max_call){
                //通话的次数与当前疑似的电话狂人一样
                //他可能也是电话狂人
                //取两者间电话号码较小的人
                if(strcmp(current->number,res_number) < 0){
                    strcpy(res_number,current->number);
                }
                creazyman++;
            }
            current = current->next;
        }
    }

    if(creazyman > 1){
        printf("%s %d %d\n",res_number,max_call,creazyman);
    }else{
        printf("%s %d\n",res_number,max_call);
    }
    return 0;
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐