力扣706:设计哈希映射

news2024/9/27 19:24:50

题目:

不使用任何内建的哈希表库设计一个哈希映射(HashMap)。

实现 MyHashMap 类:

  • MyHashMap() 用空映射初始化对象
  • void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中,则更新其对应的值 value 。
  • int get(int key) 返回特定的 key 所映射的 value ;如果映射中不包含 key 的映射,返回 -1 。
  • void remove(key) 如果映射中存在 key 的映射,则移除 key 和它所对应的 value 。

示例:

输入:
["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"]
[[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]]
输出:
[null, null, null, 1, -1, null, 1, null, -1]

解释:
MyHashMap myHashMap = new MyHashMap();
myHashMap.put(1, 1); // myHashMap 现在为 [[1,1]]
myHashMap.put(2, 2); // myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(1);    // 返回 1 ,myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(3);    // 返回 -1(未找到),myHashMap 现在为 [[1,1], [2,2]]
myHashMap.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]](更新已有的值)
myHashMap.get(2);    // 返回 1 ,myHashMap 现在为 [[1,1], [2,1]]
myHashMap.remove(2); // 删除键为 2 的数据,myHashMap 现在为 [[1,1]]
myHashMap.get(2);    // 返回 -1(未找到),myHashMap 现在为 [[1,1]]

提示:

  • 0 <= key, value <= 106
  • 最多调用 104 次 putget 和 remove 方法

思路:

哈希函数:能够将集合中任意可能的元素映射到一个固定范围的整数值,并将该元素存储到整数值对应的地址上。
冲突处理:由于不同元素可能映射到相同的整数值,因此需要在整数值出现“冲突”时,进行冲突处理。以下代码使用的解决冲突处理的方法是链地址法。

链地址法:为每个哈希值维护一个链表,并将具有相同哈希值的元素都放入这一链表当中。

设哈希表的大小为HSIZE,则可以设计一个简单的哈希函数计算哈希值x,x=key%HSIZE。

我们开辟一个大小为 HSIZE的数组,数组的每个位置是一个链表。当计算出哈希值之后,就插入到对应位置的链表当中。

由于我们使用整数除法作为哈希函数,为了尽可能避免冲突,应当将HSIZE 取为一个质数。

代码:

typedef struct List
{
    int key;
    int val;
    struct List* next;
}List;

void Insret(List* l1,int key,int val)
{
    if(l1==NULL)
        return;
    List* p=(List*)malloc(sizeof(List));
    p->key=key;
    p->val=val;
    p->next=l1->next;
    l1->next=p;
}

void Delete(List* l1,int key)
{
    if(l1==NULL)
        return;
    struct List* p=l1;
    struct List* q=p->next;
    for(;p->next!=NULL;p=p->next)
    {
       if(p->next->key==key)
       {
           q=p->next;
           p->next=q->next;
           free(q);
           break;//不加的话会有崩溃的风险
       } 
    }
}

List* Search(List* l1,int key)
{
    if(l1==NULL)
        return NULL;
    List* p=l1->next;
    for(;p!=NULL;p=p->next)
    {
        if(p->key==key)
        {
            return p;
        }
    }
    return NULL;
}

void Free(List* l1)
{
    if(l1==NULL)
        return;
    List* p=l1->next;
    while(l1->next!=NULL)
    {
        p=l1->next;
        l1->next=p->next;
        free(p);
    }
}

typedef struct {
    List* data;
} MyHashMap;

#define HSIZE 101

MyHashMap* myHashMapCreate() {
    MyHashMap* myhash=(MyHashMap*)malloc(sizeof(MyHashMap));
    myhash->data=(List*)malloc(sizeof(List)*HSIZE);
    for(int i=0;i<HSIZE;i++)
    {
        myhash->data[i].next=NULL;
    }
    return myhash;
}

void myHashMapPut(MyHashMap* obj, int key, int value) {
    if(obj==NULL)
        return;
    List* p=Search(&(obj->data[key%HSIZE]),key);
    if(p==NULL)
    {
        Insret(&(obj->data[key%HSIZE]),key,value);
    }
    else 
    {
        p->val=value;
    }
}

int myHashMapGet(MyHashMap* obj, int key) {
    if(obj==NULL)
        return -1;
    List* p=Search(&(obj->data[key%HSIZE]),key);
    if(p==NULL)
        return -1;
    else
        return p->val;
}

void myHashMapRemove(MyHashMap* obj, int key) {
    if(obj==NULL)
        return;
    Delete(&(obj->data[key%HSIZE]),key);
}

void myHashMapFree(MyHashMap* obj) {
    if(obj==NULL)
        return;
    for(int i=0;i<HSIZE;i++)
    {
        Free(&(obj->data[i]));
    }
    free(obj->data);
}

/**
 * Your MyHashMap struct will be instantiated and called as such:
 * MyHashMap* obj = myHashMapCreate();
 * myHashMapPut(obj, key, value);
 
 * int param_2 = myHashMapGet(obj, key);
 
 * myHashMapRemove(obj, key);
 
 * myHashMapFree(obj);
*/

心得:

        一开始编写Search函数时,将其返回值设为int,即int Search(),返回结果为对应key值的value值,但在后续编写void myHashMapPut()函数的过程中发现,根据题目要求,我们需要获取对应key值的节点来修改value值,所以将Search函数的返回值改为List*。

        在void Delete(List* l1,int key)函数中的for循环语句中,需要加上break,否则如果删除的是此链表的最后一个数据时,会再次执行循环语句,即使用空指针NULL,造成崩溃。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1486227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式学习笔记 - 设计原则 - 8.迪米特法则(LOD)

前言 迪米特法则&#xff0c;是一个非常实用的原则。利用这个原则&#xff0c;可以帮我们实现代码的 “高内聚、松耦合”。 围绕下面几个问题&#xff0c;来学习迪米特原则。 什么是 “高内聚、松耦合”&#xff1f;如何利用迪米特法则来实现 高内聚、松耦合&#xff1f;哪些…

【python debug】python常见编译问题解决方法_2

序言 记录python使用过程中碰到的一些问题及其解决方法上一篇&#xff1a;python常见编译问题解决方法_1 1. PermissionError: [Errno 13] Permission denied: ‘/lostfound’ 修改前&#xff1a; 修改后&#xff08;解决&#xff09;&#xff1a; 此外&#xff0c;可能文件夹…

开发者38万+,鸿蒙开发岗为何却无人敢应聘?

鸿蒙校园公开课已走进135家高校&#xff0c;305所高校学生参与鸿蒙活动&#xff0c;286家企业参加鸿蒙生态学堂&#xff0c;38万开发者通过鸿蒙认证。 居上华为官方是说有通过鸿蒙开发者认证的已有38万。具体有多少开发者并没有明确表示。除此之外还有200家头部应用加速鸿蒙原…

机器人 标准DH与改进DH

文章目录 1 建立机器人坐标系1.1 连杆编号1.2 关节编号1.3 坐标系方向2 标准DH(STD)2.1 确定X轴方向2.2 建模步骤2.3 变换顺序2.4 变换矩阵3 改进DH(MDH)3.1 确定X轴方向3.2 建模步骤3.3 变换顺序3.4 变换矩阵4 标准DH与改进DH区别5 Matlab示例参考链接1 建立机器人坐标系 1.1…

Java二叉树(1)

&#x1f435;本篇文章将对二叉树的相关概念、性质和遍历等知识进行讲解 一、什么是树 在讲二叉树之前&#xff0c;先了解一下什么是树&#xff1a;树是一种非线性结构&#xff0c;其由许多节点和子节点组成&#xff0c;整体形状如一颗倒挂的树&#xff0c;比如下图&#xff1…

探索设计模式的魅力:备忘录模式揭秘-实现时光回溯、一键还原、后悔药、历史的守护者和穿越时空隧道

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;并且坚持默默的做事。 备忘录模式揭秘-实现时光回溯、一键还原、后悔药和穿越时空隧道 文章目录 一、案例场景&…

Docker架构概述

Docker是基于Go语言实现的开源容器项目&#xff0c;能够把开发的应用程序自动部署到容器的开源的应用容器引擎。Docker的构想是要实现"Build, Ship and Run Any App, Anywhere"&#xff0c;即通过对应用的封装(Packaging)、分发(Distribution)、部署(Deployment)、运…

Autosar Appl介绍

AUTOSAR架构中的应用层 AUTOSAR 应用层构成AUTOSAR 架构中的最顶层,被认为对所有车辆应用至关重要。AUTOSAR 标准使用“组件”概念指定应用层实现。 在谈论应用层实现时,应该考虑的三个最重要的部分是: AUTOSAR 应用软件组件这些组件的 AUTOSAR 端口AUTOSAR 端口接口 AUTOS…

LeetCode受限条件下可到达节点的数目

题目描述 现有一棵由 n 个节点组成的无向树&#xff0c;节点编号从 0 到 n - 1 &#xff0c;共有 n - 1 条边。 给你一个二维整数数组 edges &#xff0c;长度为 n - 1 &#xff0c;其中 edges[i] [ai, bi] 表示树中节点 ai 和 bi 之间存在一条边。另给你一个整数数组 restr…

Game With Sticks

最近思维实在是不活跃。。。。。。 题目链接&#xff1a;Submit - Codeforces 解题思路&#xff1a; 如果n > m,交换 直接判断n就行&#xff0c;偶数M赢&#xff0c;奇数A赢 下面是c代码&#xff1a; #include<iostream> using namespace std; int main() {int n…

iZotope RX 10:专业音频修复,尽在指尖 mac/win版

iZotope RX 10是一款革命性的音频修复和增强软件&#xff0c;它为音频专业人士、电影制片人、音乐制作人和广播工作者提供了无与伦比的工具集&#xff0c;以处理和改善各种音频问题。 iZotope RX 10 软件获取 RX 10的核心是其先进的音频分析和修复算法&#xff0c;这些算法能够…

经典目标检测网络Yolo——原理部分

目标检测问题 分为两个子问题: 找到图片中哪些位置、哪些区域含有目标对象识别这些区域中的目标对象是什么基于CNN的目标检测算法能够很好的解决第二个问题,在一张图片仅含一个对象,且该对象占据了整张图片绝大部分面积时,基于CNN的对象识别算法具有很高的准确率。 一种定…

基于YOLOv的目标追踪与无人机前端查看系统开发

一、背景与简介 随着无人机技术的快速发展&#xff0c;目标追踪成为无人机应用中的重要功能之一。YOLOv作为一种高效的目标检测算法&#xff0c;同样适用于目标追踪任务。通过集成YOLOv模型&#xff0c;我们可以构建一个无人机前端查看系统&#xff0c;实现实时目标追踪和可视化…

搜素题目(蓝桥杯 C++ 代码+注解)

目录 题目一&#xff08;小朋友崇拜圈&#xff09;&#xff1a; 代码&#xff1a; 题目二&#xff08;穿越雷区&#xff09;&#xff1a; 代码&#xff1a; 题目三&#xff08;分考场&#xff09;&#xff1a; 代码&#xff1a; 题目四&#xff08;受伤的皇后&#xff09…

c++之旅——第三弹

大家好啊&#xff0c;这里是c之旅第三弹&#xff0c;跟随我的步伐来开始这一篇的学习吧&#xff01; 如果有知识性错误&#xff0c;欢迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 创作不易&#xff0c;希望大家多多支持哦&#xff01; 一.命名空间;…

基于springboot实现图书馆管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现图书馆管理系统演示 摘要 电脑的出现是一个时代的进步&#xff0c;不仅仅帮助人们解决了一些数学上的难题&#xff0c;如今电脑的出现&#xff0c;更加方便了人们在工作和生活中对于一些事物的处理。应用的越来越广泛&#xff0c;通过互联网我们可以更方便地…

OpenCV 4基础篇| OpenCV图像的拼接

目录 1. Numpy (np.hstack&#xff0c;np.vstack)1.1 注意事项1.2 代码示例 2. matplotlib2.1 注意事项2.2 代码示例 3. 扩展示例&#xff1a;多张小图合并成一张大图4. 总结 1. Numpy (np.hstack&#xff0c;np.vstack) 语法结构&#xff1a; retval np.hstack(tup) # 水平…

从嵌入式Linux到嵌入式Android

最近开始投入Android的怀抱。说来惭愧&#xff0c;08年就听说这东西&#xff0c;当时也有同事投入去看&#xff0c;因为恶心Java&#xff0c;始终对这玩意无感&#xff0c;没想到现在不会这个嵌入式都快要没法搞了。为了不中年失业&#xff0c;所以只能回过头又来学。 首先还是…

考研数学——高数:微分方程

一、一阶线性微分方程 两种形式&#xff1a; 非齐次&#xff1a; 齐次&#xff1a; 推导过程 推导公式的过程一般由特殊到一般&#xff1a;所以先求解齐次方程的解 &#xff08;然后对等式两边同时积分&#xff09; 再来求非齐次方程的解&#xff0c;由…

基于springboot实现保险信息网站系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现保险信息网站系统演示 摘要 随着互联网的不断发展&#xff0c;现在人们获取最新资讯的主要途径来源于网上新闻&#xff0c;当下的网上信息宣传门户网站的发展十分的迅速。而保险产品&#xff0c;作为当下人们非常关注的一款能够给人们带来医疗、生活、养老或…