乐理速记(一)- 调式
一、 自然大调 又名:自然大调式 举例:1 = C,即为C自然大调,简称C大调 音程:全全半全全全半 1.1 自然大调 白键 C大调:C-D-E-F-G-A-B D大调:D-E-♯F-G-A-B-♯C E大调:E-♯F-♯G-A-B-♯C-♯D F大调:F-G-A-♭B-C-D-E G大调:G-A-B-C-D-E-♯F A大调:A-B-♯C-D-E-♯F-G B大调:B-♯C-♯D-E-♯F-♯G-♯A 1.2 自然大调 黑键 原则情况:使用升号音名或降号音名都可以 实际情况:使用降号音名较多,原因是写法更简单,使用的升降号更少 ♭D大调:♭D-♭E-F-♭G-♭A-♭B-C ♭E大调:♭E-F-G-♭A-♭B-C-D ♭G大调:♭G-♭A-♭B-♭C-♭D-♭E-F ♭A大调:♭A-♭B-C-♭D-♭E-F-G ♭B大调:♭B-C-D-♭E-F-G-A 二、自然小调 又名:自然小调式 举例:1 = A,即为A自然小调,简称A小调 音程:全半全全半全全 关系大小调(平行大小调): 关系大调根音 = 小调根音 + 1.5...
Git 基本构成及常见问题
本文适合人群:具备 Git 基本使用经验的软件开发工程师、测试工程师、运维工程师等 本文学习目的:理解 Git 中最基本原理部分,以求触类旁通,在遇到突发问题时具备自行分析能力 建议阅读时间:30分钟 一、基本构成 Git由 对象库(Object store) 和 索引(index) 构成。 1.1 对象库 主要包含4种类型原子对象 :块(blob)、目录树(tree)、提交(commit)、标签(tag)。 块: 文件的每一个版本表示为一个块, 保存文件数据, 但不包含任何关于这个文件的元数据, 连文件名都没有 blob: ”binary large object” 二进制大对象 目录树: 代表一层目录信息, 记录blob标识符/路径名/和目录中所有文件的一些元数据, 也可以递归引用其他目录树和子树对象, 本质上为树形数据结构存储 提交: 保存版本库中每一次变化的元数据, 包括作者/提交者/提交日期和日志信息.每个提交对象指向一个目录树对象, 这个目录树对象在一张完整的快照中捕获提交时版本库的状态 标签:...
如果根DNS服务器被炸了,万维网是不是将马上瘫痪?
前言 最近刚追完杨导的电视剧版《三体》,对人类所为对世界的影响有了一个叹为观止的新认知,虽然是一部科幻剧,对人性的揭示却是非常刻骨。很久之前曾经在知乎刷到过一个问答,标题大概是《假如有人把支付宝所有存储服务器炸了,大众在支付宝里的钱是不是就都没有了呢?》,惭愧的说,从那篇文章笔者首先是全面地了解了「如何使用各种手段对服务集群进行物理破坏」,再者才是明白了「金融系统设计者是如何用心良苦地设计一套安全体系来保护数据」。 而偶然间在查阅一段资料时访问 root-servers ,便想到了标题的这个问题。带着这个疑问,决定追溯下去… 一、认识DNS 要回答这个问题之前,本着刨根问底的精神,首先需要了解DNS的工作原理,了解根域名的管理机制。 1.1 什么是 DNS 熟知 TCP/IP协议 可得,网络层通过定义 IP(Internet Protocol),来进行 将数据从一个设备传输到另一个设备。基于这个设想,设计出了 IP地址 概念对设备进行编号,对于 IPv4 协议, IP 地址共 32 位,分成了四段(比如,192.168.100.1),每段是 8 位。关于...
深入探究ECDHE算法
一、加密与数论基础 在正式谈及 ECDHE 之前,需要先谈谈与之关系紧密的 RSA 算法。ECDHE 是建立在优化 RSA 部分特性的前提下诞生的。 1.1 非对称加密 RSA算法 常应用于非对称加密,非对称加密生成一对密钥,常见的使用场景为: 公钥加密,私钥解密。这个目的是为了保证数据传输安全性,因为被公钥加密的内容,其他人是无法解密的,只有持有私钥的人,才能解密出实际的内容; 私钥加密,公钥解密。这个目的是为了保证数据真实性,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。 想要理解 RSA算法,首先需要从几个初等数论概念着手。 1.2 素数 素数又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。 比如:2、3、5、7、11、13、17、19 … 而素数已被证明有无穷多个,共有6种证法(分别为 欧几里得法,埃尔米特法,戈德巴赫法,弗斯滕伯格法,菲利普法),其中 欧几里得法 最为经典,论证过程可参考《几何原本》第9卷。 1.3 模运算 模运算:即...
删除链表的倒数第 N 个结点(LeetCode No.19)
一、算法思路 1.1 建模 本题思路上基本与 链表中倒数第k个节点(剑指offer No.22) 一致。直接采用 等距离位移法, 确认了要删除的位置 n 的前一位置,即 n + 1 位,而后就是常规的 删除单链表结点操作。 核心需要: 定义新链表的 虚拟头结点 通过 等距离位移法 找到 倒数第 n + 1 位 结点 nNode 断开 nNode下一位结点 1.2 注意事项 需要定义 虚拟头结点 chain,防止出现空指针的情况。比如:list.count == 10,n == 10,此时需要删除的目标位为第一位,需要 find 到第 11 位,如果没有头结点需要处理溢出情况。 单链表删除结点操作不赘述,需要可直接看代码。 二、核心代码 12345678910func removeKthFromEnd(list: SingleLinkNode<Int>, n: Int) -> SingleLinkNode<Int>? { let chain = SingleLinkNode(val: -1) chain.next =...
链表的中间结点(LeetCode No.876)
一、算法思路 1.1 建模 本题类似 链表中倒数第k个节点(剑指offer No.22) 中初始思路一样,无法直接得到单链表的长度 n,所以无法在一次遍历前提下确认 n /2 个结点。 上述文章采用 等距离位移法, 确认了目标位置。而在本题中k即为n / 2,无法直接采用相同思路建模。思考下,要在一个序列中如何在遍历时同步拉开一半距离?换个角度:甲乙两人围着操场跑一圈,什么情况下当甲到达终点(即一圈)时,乙刚好跑一半?是不是乙的速度是甲的一半时,刚好具备?这不刚好就是 快慢指针 ? 快慢指针通常用于 “判断链表是否有环” ,但在本题中也适用。 核心需要: 两个偏移指针,slow 每次偏移1步, fast 每次偏移2步 结束条件:fast 遍历结束 1.2 注意事项 fast 指针的结束边界需要严格限定,防止溢出。 二、核心代码 123456789101112func getMiddleNode(list: SingleLinkList<Int>) -> SingleLinkNode<Int>? { if...
链表中倒数第k个节点(剑指offer No.22)
一、算法思路 1.1 建模 先从最简单的思路开始,从前往后寻找第 k 个结点,一个 for循环搞定,时间复杂度 O(n)。但是如何寻找从后往前数的第 k 个节点呢? 假设链表有 n 个结点,亦即倒数第 k 个结点 位置为 n - k + 1。如果第一遍遍历确认了 n 的大小,需要第二次遍历寻找倒数第 k 个结点 ,实际上需要总遍历次数即为2次。如何减少遍历次数?能否做到一次结束?答案是肯定的,基本思路采用 “等距位移法”,即使用一个指针 p1 从 head 开始偏移 k 位,此时该指针距离head恒等于 k,此时再使用另一个指针 p2 从 head 开始,和 p1 同步偏移,整个过程中 p1 - p2 = k。当 p1 到 尾结点 的 next 时, p2 即为 第 k 个结点。 核心需要: 两个偏移指针,p1 用于先行偏移 k 位,而后 p2 随 p1 同步位移 结束条件:p1 遍历结束 ∵ p1 - p2 = k,∴ p2 = p1 - k ;当p1 = tail.next 时,p2 出于倒数第 k 位 1.2 注意事项 p1从头结点开始偏移,注意位移边界为 0...
分隔链表(LeetCode No.86)
一、算法思路 1.1 建模 本题和 合并两个有序链表(LeetCode No.21) 形式上比较相似,合并两个有序链表时是合二为一,而本题为逆向即一分为二。主要思路:把原链表分成两个链表l1、l2,l1中的元素大小都小于 x,l2中的元素都大于等于 x,最后再把这两条链表接到一起。 核心需要: 新建两条单链表 l1、l2 两个偏移指针,用于标记 l1、l2 当前的尾结点 偏移指针p,用于遍历原链表 对链表结点数据域的比对 x 的方法 拼接 l1、l2,输出结果 1.2 注意事项 新创建的单链表可以使用「虚拟头结点」,也就是 l1.head、l2.head 节点。利用虚拟头结点进行占位,可以避免空指针边界异常,降低代码的复杂性。 每次获取结点p拼接到对应新链表后,需要断开 p.next。 二、核心代码 1234567891011121314151617181920212223func partitionLinkList(list: SingleLinkList<Int>, x: Int) ->...