ARTS 第21周

ARTS 第21周分享

[TOC]

Algorithm

242. Valid Anagram

[easy]
[题目描述]

Given two strings s and t , write a function to determine if t is an anagram of s.

Example 1:
Input: s = "anagram", t = "nagaram"
Output: true

Way One:

[解题思路]
  • 将字符串按照每个字符的值的大小排序,
  • 比较两个byte slice 是否相等
[参考代码]
type myBytes []byte

func (my myBytes) Len() int {
    return len(my)
}

func (my myBytes) Less(i int, j int) bool {
    return my[i] < my[j]
}

func (my myBytes) Swap(i int,j int) {
    my[i], my[j] = my[j], my[i]
}

func isAnagram(s, t string) bool {
    //* 将字符串按照每个字符的值的大小排序,比较两个byte slice 是否相等
    // 1. 将连个字符串进行排序

    if len(s) != len(t) {
        return false
    }

    sByte, tByte := make(myBytes, len(s)), make(myBytes, len(s))
    for i:=0;i < len(s) ; i++ {
        sByte[i] = s[i]
        tByte[i] = t[i]
    }

    sort.Sort(sByte)
    sort.Sort(tByte)
    s = string(sByte)
    t = string(tByte)

    // 2. 比较大小
    if s== t {
        return true
    }
    return false
}

Way Two:

[解题思路]
  • 通过一个长度为26的映射表,用来代表26个字母,(我用[]int代替),遍历s和t中的每一个字符,s负责加1,t负责减1
  • 如果最后的表中,每一个字母的个数为零则相等,不为零则不相等
[参考代码]
func isAnagram(s, t string) bool {
    // 通过一个长度为26的hash表,遍历s和t,s负责加,t负责减,
    // 如果最后结果为零则相等,不为零则不相等
    if len(s) != len(t) {
        return false
    }

    res := make([]int, 26)
    for i := 0; i < len(s); i++ {
        res[s[i]-'a']++
        res[t[i]-'a']--
    }

    for i:=0; i<26; i++ {
        if res[i] != 0 {
            return false
        }
    }
    return true
}

Review

Using Go Moduleshttps://blog.golang.org/using-go-modules

  • go.mod 只能出现在 模块的根目录中

  • go command 通过使用列于 在 go.mod 中特定的依赖,来解决路径依赖问题

  • 当发现某个导入的包在你的任何模块中都没有提供, go command 就会自动为你搜索包含了这个包的模块,并将这个模块的最新版本添加到 go.mod中

  • 只有直接依赖模块才会被记录到 go.mod中(如果直接依赖的模块中依赖了另一个模块,即间接依赖是不会被记录在go.mod中)

  • 由于添加一个直接依赖通常也会添加一个间接的依赖,使用go list -m all就能显示当前的模块以及它的所有依赖

  • 一个语义化版本包含三部分:主版本号.次版本号.修订号( major, minor, and patch)

    • 主版本号(major):当你做了不兼容的 API 修改
    • 次版本号(minor):当你做了向下兼容的功能性新增
    • 修订号(补丁,patch):当你做了向下兼容的问题修正
  • 通常,传递给go get的每一个参数可以是具体的版本,默认类@latest,它可以解析为之前定义的最新版

  • 当导入同一个模块的不同主版本时将会使用不同的模块路径,比如当导入rsc.io/quote的 V3版时,模块路径不再是rsc.io/quote, 而是rsc.io/quote/V3

    这种思想被称为语义化版本导入, 它给了不兼容的版本(主版本)不同的命名。

  • go comand 只允许导入任意一个模块路径的一个版本,也就是说每一个主版的中的一个

    • 在一项目中:允许导入同一个模块的不同主版本,不允许导入同一个模块的不同副版本或者修订版

Tips

GO MODULE的使用方式

  • 发布版本:Go 1.11

  • 开启方式: GO111MODULE=on

    • GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
    • GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查
    • GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
      当前目录在GOPATH/src之外且该目录包含go.mod文件
      当前文件在包含go.mod文件的目录下面。
  • 项目 启用了 go modules 之后,引用包必须跟 go mod 文件第一行包名一样

  • 当modules 功能启用时,依赖包的存放位置变更为$GOPATH/pkg,允许同一个package多个版本并存,且多个项目可以共享缓存的 module。

  • 初始化Module:在GOPATH 目录之外新建一个目录,并使用go mod init 初始化生成go.mod 文件

  • go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。

  • go.mod 提供了module, require、replace和exclude 四个命令

  • module 语句指定包的名字(路径)

  • require 语句指定的依赖项模块

  • replace 语句可以替换依赖项模块

  • exclude 语句可以忽略依赖项模块

  • go module 安装 package 的原則是先拉最新的 release tag,若无tag则拉最新的commit,详见 Modules官方介绍。 go 会自动生成一个 go.sum 文件来记录 dependency tree

    • 可以使用命令 go list -m -u all 来检查可以升级的package
    • 使用go get -u need-upgrade-package 升级后会将新的依赖版本更新到go.mod
    • 也可以使用 go get -u 升级所有依赖
  • go modules 是一个版本化依赖管理系统,版本需要遵循一些规则,比如版本号需要遵循以下格式:

vX.Y.Z 是我们仓库打的标签版本,也就是 go modules 是根据仓库标签来确定版本号的,因此我们发布版本时,需要给我们的仓库打上一个标签版本号。

share

Go scheduler: https://mp.weixin.qq.com/s/Brby6D7d1szUIBjcD_8kfg

  1. Go scheduler 的主要功能是针对在处理器上运行的 OS 线程分发可运行的 Goroutine

  2. Go调度器GPM:

  • G:Goroutine,实际上我们每次调用 go func 就是生成了一个 G。

  • P:处理器,一般为处理器的核数,可以通过 GOMAXPROCS 进行修改。

  • M:OS 线程

  1. 这三者交互实际来源于 Go 的 M: N 调度模型,也就是 M 必须与 P 进行绑定,然后不断地在 M 上循环寻找可运行的 G 来执行相应的任务

  2. 当我们执行 go func() 时,实际上就是创建一个全新的 Goroutine,我们称它为 G。新创建的 G 会被放入 P 的本地队列(Local Queue)或全局队列(Global Queue)中,准备下一步的动作。

  3. 唤醒或创建 M 以便执行 G。M不断地进行事件循环寻找在可用状态下的 G 进行执行任务

  4. 全局和本地这两类队列,其实在功能上来讲都是用于存放正在等待运行的 G,但是不同点在于,本地队列有数量限制,不允许超过 256 个。并且在新建 G 时,会优先选择 P 的本地队列,如果本地队列满了,则将 P 的本地队列的一半的 G 移动到全局队列,这其实可以理解为调度资源的共享和再平衡。

  5. steal 行为,这是用来做什么的呢,我们都知道当你创建新的 G 或者 G 变成可运行状态时,它会被推送加入到当前 P 的本地队列中。但其实当 P 执行 G 完毕后,它也会 “干活”,它会将其从本地队列中弹出 G,同时会检查当前本地队列是否为空,如果为空会随机的从其他 P 的本地队列中尝试窃取一半可运行的 G 到自己的名下。

  6. 自旋线程的这个说法,是因为 Go Scheduler 的设计者在考虑了 “OS 的资源利用率” 以及 “频繁的线程抢占给 OS 带来的负载” 之后,提出了 “Spinning Thread” 的概念。也就是当 “自旋线程” 没有找到可供其调度执行的 Goroutine 时,并不会销毁该线程 ,而是采取 “自旋” 的操作保存了下来。虽然看起来这是浪费了一些资源,但是考虑一下 syscall 的情景就可以知道,比起 “自旋",线程间频繁的抢占以及频繁的创建和销毁操作可能带来的危害会更大。

hash冲突

定义: 不同的值,hash得到相同的结果,造成冲突

解决方法:

  1. 开放定址法

    从发生冲突的那个单元起,按照一定的次序,从哈希表中找到一个空闲的单元。然后把发生冲突的元素存入到该单元的一种方法。开放定址法需要的表长度要大于等于所需要存放的元素。
    在开放定址法中解决冲突的方法有:线行探查法、平方探查法、双散列函数探查法。
    开放定址法的缺点在于删除元素的时候不能真的删除,否则会引起查找错误,只能做一个特殊标记。只到有下个元素插入才能真正删除该元素。

  2. 再哈希法
    这种方法是同时构造多个不同的哈希函数:Hi=RH1(key) i=1,2,…,k。当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。

  3. 链地址法 (hash table
    这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

主键和外键

定义:

  • 主键:唯一标识一条记录,不能有重复,不允许为空。
  • 外键:表的外键是另一表的主键,外键是可以有重复的,可以是空值。
  • 索引:该字段没有重复值,但可以有一个空值。

作用:

  • 主键:用来保证数据完整性
  • 外键:用来和其他表建立联系用 (关联修改, 主键和外键就是起约束作用)
  • 索引:用来提高查询排序的速度

个数:

  • 主键:主键只能有一个。
  • 外键:一个表可以有多个外键。
  • 索引:一个表可以有多个唯一索引。

外键取值规则:空值或参照的主键值
(1)插入非空值时,如果主键值中没有这个值,则不能插入
(2)更新时,不能改为主键表中没有的值
(3)删除主键表记录时,可以在建外键时选定外键记录一起联删除还是拒绝删除
(4)更新主键记录时,同样有级联更新和拒绝执行的选择

标记清除算法(Mark And Sweep)

  1. 此算法主要有两个主要的步骤:

    ​ 第一步,找出不可达的对象,然后做上标记。 第二步,回收标记好的对象。

  2. 需要额外注意:mark and sweep算法在执行的时候,需要程序暂停!即stop the world。 也就是说,这段时间程序会卡在哪儿。故中文翻译成卡顿。

  3. 还存在一些问题:标记需要扫描整个heap, 清除数据会产生heap碎片, mark-and-sweep 算法会暂停整个程序

本周阅读

第三周:1,  4, 5, 6
websocket: https://mp.weixin.qq.com/s/gasQHCRj5RutsBe0zbSTFg
用 GODEBUG 看调度跟踪: https://mp.weixin.qq.com/s/Brby6D7d1szUIBjcD_8kfg
java打日志: https://mp.weixin.qq.com/s/OO6lhyfEJZApFst3St5TWw
深入理解 Go map:初始化和访问元素: https://mp.weixin.qq.com/s/_ySv1v8kacvPjwqm2Z8B-Q
解决哈希冲突的常用方法分析: https://www.jianshu.com/p/4d3cb99d7580
为什么 MySQL 索引要使用 B+树而不是其它树形结构?比如 B树?https://mp.weixin.qq.com/s/H2EjokOX0HHJtGYS2lbLUA

SQL的主键和外键的作用: https://www.jianshu.com/p/394f8aa724f4

图解Golang的GC算法: https://juejin.im/post/5c8525666fb9a049ea39c3e6

Go Modules详解:  http://objcoding.com/2018/09/13/go-modules/   // Good article
go mod 使用: https://juejin.im/post/5c8e503a6fb9a070d878184a
跳出Go module的泥潭:  https://colobu.com/2018/08/27/learn-go-module/
Using Go Modules: https://blog.golang.org/using-go-modules  // Good Article
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容