惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
A
About on SuperTechFans
Apple Machine Learning Research
Apple Machine Learning Research
The Register - Security
The Register - Security
Vercel News
Vercel News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
人人都是产品经理
人人都是产品经理
MyScale Blog
MyScale Blog
云风的 BLOG
云风的 BLOG
博客园_首页
U
Unit 42
T
Tailwind CSS Blog
G
GRAHAM CLULEY
F
Full Disclosure
V
Vulnerabilities – Threatpost
T
Tenable Blog
月光博客
月光博客
P
Privacy & Cybersecurity Law Blog
P
Privacy International News Feed
K
Kaspersky official blog
Scott Helme
Scott Helme
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
News and Events Feed by Topic
T
The Exploit Database - CXSecurity.com
N
News and Events Feed by Topic
有赞技术团队
有赞技术团队
Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
LINUX DO - 最新话题
Recorded Future
Recorded Future
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Help Net Security
Help Net Security
The GitHub Blog
The GitHub Blog
Cisco Talos Blog
Cisco Talos Blog
SecWiki News
SecWiki News
P
Proofpoint News Feed
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
罗磊的独立博客
S
Security Affairs
M
MIT News - Artificial intelligence
L
LINUX DO - 热门话题
美团技术团队
Simon Willison's Weblog
Simon Willison's Weblog
T
Threat Research - Cisco Blogs
Stack Overflow Blog
Stack Overflow Blog
Forbes - Security
Forbes - Security
Hugging Face - Blog
Hugging Face - Blog
博客园 - Franky
V
Visual Studio Blog

博客园 - xcywt

IT人备考心得分享 一个大龄程序员的回乡记 一种刚接触的语法。只在linux可用 固件打包流程 malloc底层实现以及和new的比较 C++异步调用 future async promise packaged_task 如果在单例模式中返回share_ptr ??? Qt实现自定义控件-按钮 一个线程池的例子 C++ 条件变量condition_variable的例子 C++中share_ptr中循环引用的问题 C++14的一些新特性 C++11的一些特性 ubuntu编译grpc & protobuf perf笔记 一个cmakelist的例子(自动处理多个proto) Linux下eCal测试计划及进度记录 windows编译ecal 记录一次重装gitlab
记录一道面试题(哈希表 稀疏矩阵)
xcywt · 2024-10-10 · via 博客园 - xcywt

题目:

有一个游戏中的三维地图,是由i,j,k三个轴组成的三维网络。每个立方体由不同的种类代表,比如空气,水,沙子,泥土。
地图上方的空气方块,不会经常变动且数量占大多数,下方是各种类型的方块,会经常相互转换(水变沙子,沙子变泥土等)。

问题:请你实现一个存储该地图的方案(地图方块和对应类型)。
要求:尽量减少内存空间占用,要支持高频查询。

思路:

1.首先要有整体意识,地图是一个三维坐标系,有三个轴。应该要想到用矩阵或者多维数组。

2.要注意要求中的“尽量减少内存空间占用”,由于空气多且不易变动,可以采用稀疏矩阵来存。相当于没数据的时候就是空气。

3.要支持高频查询,哈希表应该是最快的。

上代码:

blockmap.h

#ifndef BLOCKMAP_H
#define BLOCKMAP_H


#include <unordered_map>

/*
有一个游戏中的三维地图,是由ijk三个轴组成的三维网络。每个立方体由不同的种类代表,比如空气,水,沙子,泥土。
地图上方的空气方块,不会经常变动且数量占大多数,下方是各种类型的方块,会经常相互转换(水变沙子,沙子变泥土等)。

问题:请你实现一个存储该地图的方案(地图方块和对应类型)。
要求:尽量减少内存空间占用,要支持高频查询。

关键思路:
1.由于空气变动少且占用多,可以采用稀疏矩阵存储,节省内存资源。
2.用哈希表存储非空气块,方便快速查询。
*/

// 方块类型:实际项目应该还会存储别的成员。比如颜色之类的。也可以用枚举定义类型
struct Block
{
    int type = 0; // 0-空气 1-水 2-泥土 3-沙子 4-树
};

class BlockMap
{
private:
    std::unordered_map<long long, Block> blockMap; // 用哈希表存储非空气块,方便快速查询。
    const int airType = 0; // 空气类型为0
    long long encodeKey(const int& i, const int& j,const int& k) // 为了生成唯一的key,合并成一个long long
    {
        return (static_cast<long long>(i) << 40) | (static_cast<long long>(j) << 20) | k;
    }
public:
    BlockMap(){}
    //获取方块类型
    int getBlockType(const int& i, const int& j,const int& k)
    {
        long long key = encodeKey(i,j,k);
        if(blockMap.find(key) != blockMap.end())
        {
            return blockMap[key].type;
        }
        else{
            return airType; // 找不到的时候,默认就是空气。
        }
    }

    // 设置方块类型
    void setBlockType(const int& i, const int& j,const int& k, const int& type)
    {
        auto key = encodeKey(i,j,k);
        if(type == airType)
        {
            return; // 不存空气。节省内存空间。
        }
        else
        {
            Block newbk;
            newbk.type = type;
            blockMap[key] = newbk;
        }
    }
};

void BlockMapTest(); // 测试程序

#endif // BLOCKMAP_H

测试:

#include "blockmap.h"
#include <qDebug> // Qt平台的头文件。非C++标准库

void BlockMapTest()
{
    BlockMap mapTest;
    mapTest.setBlockType(1,1,1,1);
    mapTest.setBlockType(2,2,2,2);
    mapTest.setBlockType(3,3,3,3);

    qDebug() << "1,1,1 类型为:" << mapTest.getBlockType(1,1,1);
    qDebug() << "2,2,2 类型为:" << mapTest.getBlockType(2,2,2);
    qDebug() << "3,3,3 类型为:" << mapTest.getBlockType(3,3,3);
    qDebug() << "1,0,1 类型为:" << mapTest.getBlockType(1,0,1);
}

执行效果:

总结:

数据结构还是要多熟悉,自己写不出来的话要会选择最合适的。