IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Java&C++题解与拓展——leetcode380.O(1)时间插入、删除和获取随机元素【unordered_map学习与使用】 -> 正文阅读

[数据结构与算法]Java&C++题解与拓展——leetcode380.O(1)时间插入、删除和获取随机元素【unordered_map学习与使用】

每日一题做题记录,参考官方和三叶的题解

题目要求

image.png

思路:哈希表+数组

O ( 1 ) O(1) O(1)复杂度的插入和删除很明显是用哈希表,但是取随机数的话用数组返回随机下标比较方便,所以就同时维护一个哈希表和一个数组,哈希表存着数组内元素及其对应下标。

直接根据数据范围( 2 ? 1 0 5 2*10^5 2?105)申请一个固定大小的数组,为了方便取随机数,要维护数组的「 i d x idx idx个元素都不空」,所以在删除元素时要把当前最后一个元素 n u m s [ i d x ] nums[idx] nums[idx]放到被删除的元素处 n u m s [ d e l ] nums[del] nums[del]补空。
此时随机操作直接在 [ 0 , i d x ] [0,idx] [0,idx]内取随机值作为下标,返回数组内对应值即可。

而对于插入操作,则判断是否存在于哈希表中,然后同时维护哈希表和数组即可。

Java

class RandomizedSet {
    static int[] nums = new int[200001];
    Random random = new Random();
    Map<Integer, Integer> map = new HashMap<>(); //数组下标与值
    int idx = -1;
    public RandomizedSet() {}
    
    public boolean insert(int val) {
        if(map.containsKey(val))
            return false;
        nums[++idx] = val;
        map.put(val, idx);
        return true;
    }
    
    public boolean remove(int val) {
        if(!map.containsKey(val))
            return false;
        int del = map.remove(val);
        if(del != idx) //是否删除最后一个元素
            map.put(nums[idx], del);
        nums[del] = nums[idx--]; //补空,保证前面都是满的
        return true;
    }
    
    public int getRandom() {
        return nums[random.nextInt(idx + 1)];
    }
}
  • 时间复杂度:所有操作均 O ( 1 ) O(1) O(1)
  • 空间复杂度: O ( n ) O(n) O(n),数组和哈希表均为 O ( n ) O(n) O(n)

C++

class RandomizedSet {
private:
    int nums[200001];
    unordered_map<int, int> map;
    int idx = -1;
public:
    RandomizedSet() {}
    
    bool insert(int val) {
        if(map.count(val))
            return false;
        nums[++idx] = val;
        map[val] = idx;
        return true;
    }
    
    bool remove(int val) {
        if(!map.count(val))
            return false;
        int del = map[val];
        map.erase(val);
        if(del != idx) //是否删除最后一个元素
            map[nums[idx]] = del;
        nums[del] = nums[idx--]; //补空,保证前面都是满的
        return true;
    }
    
    int getRandom() {
        return nums[rand() % (idx+1)];
    }
};
  • 时间复杂度:所有操作均 O ( 1 ) O(1) O(1)
  • 空间复杂度: O ( n ) O(n) O(n),数组和哈希表均为 O ( n ) O(n) O(n)

STL unordered_map

  • 学习参考链接
  • 即为一个无序的map容器,以键值对形式存在,键不能相等。
方法功能备注
e m p l a c e ( ) emplace() emplace()插入元素,效率高于insert()
c o u n t ( k e y ) count(key) count(key)查找键值为 k e y key key的键值对个数上文使用判断是否存在键值为 k e y key key的元素
f i n d ( k e y ) find(key) find(key)查找键值为 k e y key key的键值对,返回相应正向迭代器,若未找到则返回最后一个键值对之后位置的迭代器【即 e n d ( ) end() end()方法的返回值】上文判断处也可换为此方法,即map.find(key) == map.end()则不存在,反之则存在
e r a s e ( k e y ) erase(key) erase(key)删除以 k e y key key为键的键值对

总结

想到了用哈希表,但是没有想到额外维护一个前面值均不空的数组来进行随机数的寻找。

C++的这几个容器的方法都差不多,但是定义不同存在细节差异,还是要注意区分。还有,在这里写习惯了,编译器里很容易忘掉要include相应内容……


欢迎指正与讨论!
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:24:47  更:2022-04-15 00:29:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 7:18:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码