ARTS(10)

栏目: 编程工具 · 发布时间: 5年前

内容简介:在单元测试一定要充分,现实往往是那些疏忽的单元测试出问题。

1 Algorithm

设计一个 LRU 缓存机制,使它支持 putget 操作,缓存大小是由一定限制的,如果缓存数量超出范围,则删除最近最少使用的 key ,如果 key 不存在,返回 -1 (所有的 value 值大于0),时间复杂度为$O(1)$。

为了保证时间复杂度为$O(1)$,就需要用空间换时间,为了保证更新 Key 和删除 Key 在常数时间内完成,所以采用双向链表完成,查询 Key 在常数时间内完成,则使用 字典 保存每一个 Key ,而且 Value 指向双向链表的每一个元素。依次 Put(1,1), Put(2,2), Put(3,3) 后,示意图如下:

ARTS(10) Front 节点为最近最少使用的 key , Back 节点为最近最多使用的节点。一旦 Get 命中,则将该节点中列表中摘除出来,并且添加到最后。
type Element struct {
    key  int
    value int
    prev  *Element
    next  *Element
}

type List struct {
    head *Element
    tail *Element
}

func NewList() *List {
    l := &List{
        head:∈{},
        tail:∈{},
    }
    l.head.next = l.tail
    l.tail.prev = l.head
    return l
}

func (l *List) Remove(e *Element) {
    pre, next := e.prev, e.next
    pre.next = next
    next.prev = pre
}

func (l *List) Push(e *Element) {
    e.prev = l.tail.prev
    e.prev.next = e
    e.next = l.tail
    l.tail.prev = e
}

func (l *List) Pop() *Element {
    if l.head.next == l.tail {
        return nil
    }
    e := l.head.next
    l.Remove(e)
    return e
}

type LRUCache struct {
    l        *List
    capacity int
    table    map[int]*Element
}

func Constructor(capacity int) LRUCache {
    return LRUCache{
        l:        NewList(),
        capacity: capacity,
        table:    make(map[int]*Element),
    }
}

func (this *LRUCache) Get(key int) int {
    if val, ok := this.table[key]; ok {
        this.l.Remove(val)
        this.l.Push(val)
        return val.value
    }
    return -1
}

func (this *LRUCache) Put(key int, value int) {
    if val, ok := this.table[key]; ok {
        this.l.Remove(val)
        val.value = value
        this.l.Push(val)
    }else{
        e := ∈{key:key, value:value}
        if len(this.table) < this.capacity {
            this.l.Push(e)
            this.table[key] = e
        }else{
            n:=this.l.Pop()
            delete(this.table, n.key)
            n = nil
            this.l.Push(e)
            this.table[key] = e
        }
    }
}

2 Review

Why I love refactoring

为什么我喜欢重构

我喜欢重构,如果不是显然的需求,这也是我软件开发的方法。可以甚至说,我喜欢重构超过喜欢写新需求。我几乎将圣诞假期、新年假期都用在在之前的代码中提取有用的东西。

当在重构的时候,你比当初写下第一行代码的时候更加了解这个领域,所以能够揭开无数之前的错误的假设。你也知道了这些代码在将来会怎么使用,因而更加有有序的组织它们。也知道性能方面问题是否存在,或者事实上性能是否你需要考虑的。

当你编写新的功能的时候, 代码库将会变得更加难以理解。你可能会编写一下很棒的代码,每一行的代码质量也会往上发展,但是这些都不重要的。我们都知道,大的代码库比小的代码库更加难以阅读,大代码库包含更多的文件夹,更多的文件和更多的层次设计,甚至都需要用 grep 工具来查询。但是如果使用重构,你将会往另外一个方向发展,将来的开发者在使用 git blame 的时候,会大大称赞你的名字。

还有更具有洞察力原因是重构有助于你的健康,但是这也不是我为什么喜欢重构的原因。我喜欢编写代码,既喜欢重构,也喜欢编写新的功能。但是没有比写出好的代码更加让人欣慰,没必要担心你的代码是否对别人有用,只要你自己知道就好了。你清楚地知道了使用哪种抽象,将你第一次编写功能的时候担心和优化隔离开来。

对于编写第一个版本的人保持尊重是非常重要的,他们也是聪明的人,是在你不同的限制条件下。或许联合国秘书长应该在将来24小时拍下一个快照,将来和现在都是不同的。没有人知道它的代码在将来会变得非常重要,甚至是在几年后还在运行着。他们的决定是重要的,你应该记住这一点。

不幸的是即使你有一个高品位的代码库,你也不会得到任何赞赏。但是实现它们是重要的而不是得到赞赏,要记住:让一些事变得有用起来。

3 Tips

3.1 github 更新 fork 的仓库

github 上参与开源项目, fork 一份代码仓库后,如果原仓库有更新,那么如果更新自己 fork 出来的一份呢?

  • 添加 remote 源: git remote add upstream https://github.com/whoever/whatever.git ;
  • 拉取源: git fetch upstream ;
  • 切换到 master 分支: git checkout master
  • rebase 分支: git reabse upstream/master

4 Share

单元测试一定要充分,现实往往是那些疏忽的单元测试出问题。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

无界面交互

无界面交互

[美]Golden Krishna / 杨名 / 人民邮电出版社 / 2017-1 / 49.00元

“真希望在硅谷工作的人们已经读过这本书了。”——Doug LeMoine,Cooper总经理 “这本书的写作看似随意,字里行间却透着一种辛辣、幽默的反叛精神,这种精神可以帮助我们走出当今交互设计的界面泥潭。当你心情低落时,不妨翻开这本书,读上几页,你会开始微笑,大笑,并从中学到很多东西。书中的文字有一股振奋人心的力量。”——Don Norman,加州大学圣迭戈分校设计实验室主任,《设计心理学......一起来看看 《无界面交互》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具