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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 算法---全 O(1) 的数据结构(Kotlin) -> 正文阅读

[数据结构与算法]算法---全 O(1) 的数据结构(Kotlin)

题目

请你设计一个用于存储字符串计数的数据结构,并能够返回计数最小和最大的字符串。

实现 AllOne 类:

AllOne() 初始化数据结构的对象。
inc(String key) 字符串 key 的计数增加 1 。如果数据结构中尚不存在 key ,那么插入计数为 1 的 key 。
dec(String key) 字符串 key 的计数减少 1 。
如果 key 的计数在减少后为 0 ,那么需要将这个 key 从数据结构中删除。测试用例保证:在减少计数前,key 存在于数据结构中。
getMaxKey() 返回任意一个计数最大的字符串。如果没有元素存在,返回一个空字符串 ""getMinKey() 返回任意一个计数最小的字符串。如果没有元素存在,返回一个空字符串 ""

示例:

输入
["AllOne", "inc", "inc", "getMaxKey", "getMinKey", "inc", "getMaxKey", "getMinKey"]
[[], ["hello"], ["hello"], [], [], ["leet"], [], []]
输出
[null, null, null, "hello", "hello", null, "hello", "leet"]

解释
AllOne allOne = new AllOne();
allOne.inc("hello");
allOne.inc("hello");
allOne.getMaxKey(); // 返回 "hello"
allOne.getMinKey(); // 返回 "hello"
allOne.inc("leet");
allOne.getMaxKey(); // 返回 "hello"
allOne.getMinKey(); // 返回 "leet"
 

提示:

1 <= key.length <= 10
key 由小写英文字母组成
测试用例保证:在每次调用 dec 时,数据结构中总存在 key
最多调用 inc、dec、getMaxKey 和 getMinKey 方法 5 * 104 次

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/all-oone-data-structure
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解决思路

今天这道题对于做过 LRU/LFU 相关题型的同学来说应该不难。

这一类型的题目一般都是使用 哈希表 + 双向链表 的方式来实现。

其中,哈希表存储 key->Node 的映射关系,双向链表按频率排序,对于 LRU 就是最近最少使用,对于今天这道题就是每个 key 的次数。

具体地实现上,我们可以设置 头和尾 两个 虚拟节点,这样的话,我们操作链表就不需要考虑空指针的问题了,也可以简化我们的代码。

参考:
https://leetcode.cn/problems/all-oone-data-structure/solution/by-tong-zhu-qccw/

解决方法

class AllOne() {
    var map = HashMap<String, Node>()
    var head = Node()
    var tail = Node()
    init {
        head.next = tail
        tail.pre = head
    }
    class Node() {

        var set = HashSet<String>()
        var count = 0
        var next: Node? = null
        var pre: Node? = null

        constructor(key: String,count:Int) : this() {
            set.add(key)
            this.count = count
        }

        fun insertPre(pre: Node) {
            this.pre?.next = pre
            pre.pre = this.pre
            pre.next = this
            this.pre = pre
        }

        fun insertNext(next: Node) {
            this.next?.pre = next
            next.next = this.next
            this.next = next
            next.pre = this
        }

        fun removeKey(key: String) {
            set.remove(key)
            if (set.isEmpty()){
                remove()
            }
        }

        fun addKey(key: String) {
            set.add(key)
        }

        fun remove() {
            this.next?.pre = this.pre
            this.pre?.next = this.next
        }
    }

    fun inc(key: String) {
        // 存在
        if (map.containsKey(key)) {
            val node = map[key]
            val newCount = node!!.count + 1
            if (node.next?.count != newCount) {
                //new node
                val nextNode = Node(key,newCount)
                node.insertNext(nextNode)
                map[key] = nextNode
            } else {
                //user old
                node.next!!.addKey(key)
                map[key] = node.next!!
            }
            node.removeKey(key)
        } else {
            //不存在  寻找相同数量的node
            val cur = head.next
            if (cur?.count != 1) {
                val node = Node(key,1)
                head.insertNext(node)
                map[key] = node
            } else {
                //存在1个元素
                cur.addKey(key)
                map[key] = cur
            }
        }

    }

    fun dec(key: String) {
        val node = map[key] ?: return
        val newCount = node.count - 1
        if (newCount == 0){
            map.remove(key)
        }else if (node.pre!!.count != newCount) {
            val preNode = Node(key,newCount)
            node.insertPre(preNode)
            map[key] = preNode
        } else {
            node.pre!!.addKey(key)
            map[key] = node.pre!!
        }
        node.removeKey(key)
    }

    fun getMaxKey(): String {
        return if (tail.pre == head){
            ""
        }else{
            tail.pre!!.set.iterator().next()
        }
    }

    fun getMinKey(): String {
        return if (head.next == tail){
            ""
        }else {
            head.next!!.set.iterator().next()
        }
    }
}

总结

1.自己写了一遍结果发现一晚上没有写出来,第二天再次写才写出来了
2.一步一步调试还是太慢,一遍一遍检查代码才是王道。测试用例几千次的方法调用,你没有办法调试。效率还低

展示一下我自己第一遍写过的垃圾代码:

//第一个版本  很烂  但是通过了
class AllOne() {
    var map = HashMap<String, Node>()
    var head = Node()
    var tail = Node()

    init {
        head.next = tail
        tail.pre = head
    }

    class Node {
        var set = HashSet<String>()
        var count = 0
        var next: Node? = null
        var pre: Node? = null
    }

    fun inc(key: String) {
        // 存在
        if (map.containsKey(key)) {
            val node = map[key]
            if (node!!.next?.count != node.count + 1) {
                if (node.set.size == 1) {
                    node.count ++
                } else { //new node
                    val node1 = Node()
                    node1.count = node.count + 1
                    node1.set.add(key)
                    map[key] = node1
                    node.set.remove(key)

                    node1.next = node.next
                    node1.pre = node
                    node1.pre!!.next = node1
                    node1.next!!.pre = node1
                }

            } else {
                //user old
                node.next!!.set.add(key)
                map[key] = node.next!!
                if (node.set.size == 1) {
                    node.pre!!.next = node.next
                    node.next!!.pre = node.pre
                } else {
                    node.set.remove(key)
                }
            }


        } else {
            //不存在  寻找相同数量的node
            var cur = head.next
            if (cur?.count != 1) {
                var node = Node()
                node.set.add(key)
                node.count = 1
                node.next = head.next
                node.pre = head
                node.pre!!.next = node
                node.next!!.pre = node
                map[key] = node
            } else {
                //存在1个元素
                cur.set.add(key)
                map[key] = cur
            }
        }

    }

    fun dec(key: String) {
        //
        val node = map[key]
        //只有这个自己  移除
        if (node!!.count == 1 && node.set.count() == 1) {
            node.pre?.next = node.next
            node.next?.pre = node.pre
            map.remove(key)
        } else {
            if (node.pre!!.count != node.count - 1) {
                val node1 = Node()
                node1.next = node
                node1.pre = node.pre
                node1.pre!!.next = node1
                node1.next!!.pre = node1
                node1.count = node.count - 1
                node1.set.add(key)
                map[key] = node1
                if (node.set.size == 1){
                    //remove
                    node.pre!!.next = node.next
                    node.next!!.pre = node.pre
                }else{
                    node.set.remove(key)
                }
            } else {
                if (node.pre != head){
                    node.pre!!.set.add(key)
                    map[key] = node.pre!!
                    if (node.set.count() == 1){
                        node.pre!!.next = node.next
                        node.next!!.pre = node.pre
                    }else{
                        node.set.remove(key)
                    }
                }else{
                    node.set.remove(key)
                    if (node.set.size == 0){
                        map.remove(key)
                        node.next!!.pre = node.pre
                        node.pre!!.next = node.next
                    }
                }
            }
        }
    }

    fun getMaxKey(): String {
        val pre = tail.pre
        if (pre != head) {
            return pre!!.set.iterator().next()
        }
        return ""
    }

    fun getMinKey(): String {
        val next = head.next
        if (next != tail) {
            val iterator = next!!.set.iterator()
            var result = ""
            while (iterator.hasNext()){
                result = iterator.next()
            }
            return result
        }
        return ""
    }
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-11 16:39:00  更:2022-05-11 16:40:03 
 
开发: 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 3:39:34-

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