【无标题】

哈希表(Hash Table)是一种常见的数据结构,能够快速地进行查找和插入操作。它的核心思想是利用哈希函数将关键字映射到数组的某个位置上,使得查找和插入的时间复杂度接近O(1)。

下面是C语言实现哈希表的基本步骤:

  1. 定义哈希表结构体

首先定义一个哈希表结构体,其中包含两个成员:一是数组buckets用来存储哈希表中的元素,二是size表示buckets中元素的数量。

#define TABLE_SIZE 10000 // 哈希表大小

typedef struct 
{
    int* buckets;
    int size;
} HashTable;

2.初始化哈希表

初始化哈希表时需要为buckets分配内存,并将其所有元素初始化为-1。这里用-1表示哈希表当前位置没有元素

HashTable* create_table() 
{   //根据自己需求创建哈希表的大小
    HashTable* table = (HashTable*)malloc(sizeof(HashTable));
    table->buckets = (int*)malloc(sizeof(int) * TABLE_SIZE);    
    table->size = TABLE_SIZE;

    for (int i = 0; i < TABLE_SIZE; i++)
     {
        table->buckets[i] = -1;
    }

    return table;
}

3.定义哈希函数

哈希函数的作用是将关键字映射到数组的某个位置上。一个好的哈希函数应该尽可能地避免冲突,即不同的关键字映射到相同的位置上。这里采用简单的取余法作为哈希函数

int hash(int key) 
{
    return key % TABLE_SIZE;
}

4.插入元素

插入元素时需要先对关键字进行哈希,得到它在数组中的位置。如果该位置还没有被占用,则直接插入;否则需要处理冲突,例如使用开放地址法、链地址法等方法。

void insert(HashTable* table, int key, int value) {
    int index = hash(key);

    while (table->buckets[index] != -1) 
    {
        index++;
        index %= TABLE_SIZE;
    }

    table->buckets[index] = value;
}

5.查找元素

查找元素时同样需要先进行哈希,得到它在数组中的位置。然后依次向后查找,直到找到对应的元素或者遇到空位置停止查找。

int search(HashTable* table, int key) 
{
    int index = hash(key);

    while (table->buckets[index] != -1) 
    {
        if (table->buckets[index] == key) 
        {
            return index;
        }

        index++;
        index %= TABLE_SIZE;
    }

    return -1;
}

1015. 可被 K 整除的最小整数

难度中等

136

给定正整数 k ,你需要找出可以被 k 整除的、仅包含数字 1 的最 小 正整数 n 的长度。

返回 n 的长度。如果不存在这样的 n ,就返回-1。

注意: n 不符合 64 位带符号整数。

示例 1:

输入:k = 1输出:1解释:最小的答案是 n = 1,其长度为 1。

示例 2:

输入:k = 2输出:-1解释:不存在可被 2 整除的正整数 n 。

示例 3:

输入:k = 3输出:3解释:最小的答案是 n = 111,其长度为 3

该题只需对特殊值进行判断后在进行遍历就可以了

int smallestRepunitDivByK(int k)
{

if(k%5==0 || k%2==0)
return -1;

int min=1,ans=1;

while(min % k)
{
    min = min%k;
   min = min*10 +1;
   ans ++;
}

return ans;

}

看到一个比较新奇的,用字符串进行记录,但不太明白它的原理是什么。

看了ChatGPT的解释,才晓得具体实现中,代码通过动态数组kc来记录每个余数是否出现过,如果某个余数已经出现过,则说明已经进入了一个循环。函数的返回值为最小循环长度,如果无法被K整除,则返回-1,表示不存在符合条件的数字序列。

int smallestRepunitDivByK(int K)
{
    int *kc = (int *)calloc(K, sizeof(int));
    int count = 0, i = 0;
    while (!kc[i])
    {
        kc[i] = 1;
        i = (i * 10 + 1) % K;
        count++;
    }
    return (i == 0) ? count : -1;
}

官解的哈希表,感觉和字符串判断有相似,都是判断是否掉入死循环,然后得出能否整除。

// 定义一个哈希表的元素结构体,含有键值 key 和指向哈希表的指针
typedef struct {
    int key;
    UT_hash_handle hh;
} HashItem; 

// 在哈希表中查找键值为 key 的元素,返回找到的元素指针
HashItem *hashFindItem(HashItem **obj, int key) {
    HashItem *pEntry = NULL;
    // 使用 UT_hash_handle 库中的 HASH_FIND_INT 宏实现
    HASH_FIND_INT(*obj, &key, pEntry);
    return pEntry;
}

// 在哈希表中添加键值为 key 的元素,如果已存在则返回 false,否则返回 true
bool hashAddItem(HashItem **obj, int key) {
    if (hashFindItem(obj, key)) {
        return false;
    }
    // 创建一个新的元素结构体,并设置键值
    HashItem *pEntry = (HashItem *)malloc(sizeof(HashItem));
    pEntry->key = key;
    // 使用 UT_hash_handle 库中的 HASH_ADD_INT 宏将元素添加到哈希表中
    HASH_ADD_INT(*obj, key, pEntry);
    return true;
}

// 释放哈希表 obj 中所有元素的内存
void hashFree(HashItem **obj) {
    HashItem *curr = NULL, *tmp = NULL;
    // 使用 UT_hash_handle 库中的 HASH_ITER 宏遍历哈希表
    HASH_ITER(hh, *obj, curr, tmp) {
        // 使用 UT_hash_handle 库中的 HASH_DEL 宏从哈希表中删除元素
        HASH_DEL(*obj, curr);  
        // 释放元素的内存
        free(curr);
    }
}

// 解决问题的函数
int smallestRepunitDivByK(int k) {
    // 初始化余数为 1,长度为 1,并创建一个空的哈希表
    int resid = 1 % k, len = 1;
    HashItem *st = NULL;
    // 在哈希表中添加余数
    hashAddItem(&st, resid);
    // 当余数不为 0 时,重复以下操作
    while (resid != 0) {
        // 计算下一个余数
        resid = (resid * 10 + 1) % k;
        // 长度加 1
        len++;
        // 如果哈希表中已经存在该余数,则说明已经出现循环,直接返回 -1
        if (hashFindItem(&st, resid) != NULL) {
            hashFree(&st);
            return -1;
        }
        // 在哈希表中添加余数
        hashAddItem(&st, resid);
    }
    // 释放哈希表的内存,返回长度
    hashFree(&st);
    return len;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值