实现数组的基本数据结构

  • 数组的基本数据结构的实现
  • 插入,删除, 更新

思路

数组是一系列连续的数据集合,有固定的长度和下标,根据下标访问查找时间复杂度O(1),删除时间复杂度也是O(1)。

实现目标

  • 使用Go语言实现基本的数组数据结构
  • 通过Go实现数组的基本操作

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package array

import (
"errors"
"fmt"
)

type Array struct {
data []int
length int
}

func NewArray(capcity int) *Array {
if capcity <= 0 {
return nil
}

return &Array{
data: make([]int, capcity, capcity),
length: 0,
}
}

func (self *Array) IsOutOfRange(index int) bool {
if index < 0 || index >= cap(self.data) {
return true
}

return false
}

func (self *Array) Len() int {
return self.length
}

// find specfic data index value
func (self *Array) FindIndexByData(data int) int {
for index, value := range self.data {
if value == data {
return index
}
}

return -1
}

func (self *Array) FindDataByIndex(index int) (int, error) {
if self.IsOutOfRange(index) {
return -1, errors.New("Out of range when find")
}

return self.data[index], nil
}

// Delete elements by sepecific value
func (self *Array) Delete(index int) (int, error) {
if self.IsOutOfRange(index) {
return -1, errors.New("Out of range when delete!")
}

v := self.data[index]

for i:=index; i< self.Len() - 1; i++ {
self.data[i] = self.data[i] + 1
}

self.length--

return v, nil
}

func (self *Array) Insert(index int, data int) (bool, error) {
if self.IsOutOfRange(index) {
return false, errors.New("Out of range when insert")
}

if self.Len() == cap(self.data) {
return false, errors.New("Capcity is full when insert")
}

for i := self.length-1; i >= index ; i-- {
fmt.Println("Insert: ", self.data, i, index)

self.data[i] = self.data[i-1]
}

self.data[index] = data

self.length++

return true, nil
}

func (self *Array) Append(data int) (bool, error) {

if self.Len() == cap(self.data) {
return false, errors.New("Capcity is full when insert")
}

return self.Insert(self.length, data)
}

func (self *Array) Prepend(data int) (bool, error) {
if self.Len() == cap(self.data) {
return false, errors.New("Capcity is full when insert")
}

return self.Insert(0, data)
}

func (self *Array) Print() {
var formatString string
for i :=0; i < self.length; i++ {
formatString += fmt.Sprintf("|%+v", self.data[i])
}

fmt.Println(formatString)
}

契机

最近参加了一轮大厂的面试, 直接手撕算法和数据结构, 感觉到很是挺生疏的, 简单的算法也不能很快写出来。 因此, 决定个人博客开立算法板块, 一方面重学数据结构和算法, 一方面将自己的心得记录下来。 最终目标, 可以手写常见的算法和数据结构实现,同时兼顾时间复杂度和空间复杂度, 每周至少学习一个算法。

计划

  • 基础部分

    • 数组: 查询, 插入, 删除
    • 链表: 单链表/循环链表, 插入,删除
    • 栈: 入栈,出栈, 查找
    • 队列 入队,出队,循环队列, 查找
    • 二叉树 查找(前中后序), 删除, 添加节点
    • 堆 搜索, 删除, 添加
    • HashTable 查找,添加,删除
    • 图 插入,删除,查找最短路径
  • 中等

    • 红黑树/B+树
    • 字符串匹配算法
    • 动态规划
    • 回溯算法
    • 贪心算法
  • 实用案例分析

    • 数据库索引算法
    • 实现正则表达式的匹配算法
    • 实时统计TOP N的信息
    • 推荐算法
    • 机器学习算法原理
    • 分布式算法
  • 实践

    • topcoder刷题
    • letcode刷题

反馈机制

  1. 每个课题手写完整的代码, 必须没有语法错误, 边界检查
  2. 验证时间复杂度和空间复杂度, 持续优化找出不足之处该进
  3. 到topcoder或者letcode上找一个相关的案例提交解题答案

一直对物联网安全很感兴趣, 很想从事安全方向的职业, 机缘巧合, 去年加入了一家做业务安全的公司。

安全行业

网络安全是指网络系统的硬件、软件及其系统中的数据受到保护,不因偶然的或者恶意的原因而遭受到破坏、更改、泄露,系统连续可靠正常地运行,网络服务不中断

业务安全是指保护业务系统免受安全威胁的措施或手段。广义的业务安全应包括业务运行的软硬件平台(操作系统、数据库等)、业务系统自身(软件或设备)、业务所提供的服务的安全;狭义的业务安全指业务系统自有的软件与服务的安全。

业务安全的本质是为客户省钱, 那么省钱的方式有哪些?哪些客户需要?

先来看看客户的痛点有哪些:

  1. 营销活动没有吸收到新的用户,反而被黄牛党大把大把的薅羊毛
  2. 刷量刷单现象严重,严重扰乱市场正常竞争
  3. 公司内部敏感信息泄漏,被放到暗网上销售,例如公司商业机密数据,联系方式等
  4. 二三类银行卡被用于洗钱,赌博,贷款诈骗等
  5. 业务流程存在漏洞, 例如通过修改正常的订单价格和数量来达到非法获利的目的

从以上的痛点来看,如果能够做到在以上行为发生的早期发现并预警,那么就可以为客户减少很多不必要的损失。例如去年发生的PDD被一晚上薅羊毛200亿的事件

X公司的业务模式

通过收集事件上下游的数据,来做到事前阻断,事中止损, 事后追查, 主要通过以下渠道:

  • 收码平台
    • 通过收码平台打码信息,可以知道黑灰产人员最近在注册/关注/提现等行为,然后通过提取出产品名称并且和客户做关联
  • 信息交流论坛: 如卡农社区,脉脉
    • 通过论坛贴吧知乎等渠道的沟通交流, 可以获知黑灰产人员将来或者正在对哪些产品采取非法的行动
  • 聊天工具:QQ,TG等
    • 通过获取群聊的消息,提取聊天关键字来发现潜在的恶意行为
  • 售卖平台:淘宝,京东,暗网
    • 通过对销售渠道监控,获取哪些服务被售卖和销赃

X公司的技术架构

业务模式和场景决定架构选择,架构的本质是降低复杂性, 降低成本,增加效益。业务层面主要面临的挑战:

  1. 数据渠道众多, 需要实现不同的爬虫程序来获取数据
  2. 数据量大,不同数据渠道来源的数据汇总之后每天有几十G
  3. 带宽有限, 在有限的时间传输大量的数据很快会因为带宽沾满问题导致不能及时回传
  4. 下游消费能力有限, 未优化前每秒只能处理几百条数据
  5. 数据应用T+1延迟, 当天的数据不能及时获取, 一般会有半天到一天的延迟,在某些场景下是对业务来说是致命的

针对以上问题, 我一起参与了公司的架构实现:

  1. 针对多渠道的数据定义统一的数据接口, 这样在预处理的时候可以统一处理,不需要按渠道分别处理
  2. 通过队列和缓冲,先将数据缓存到Kafka队列里, 然后通过下游多个消费者消费, 并且可以用于实时计算, 大大减少数据的延迟
  3. 数据采集层通过增加redis集群, 采用分布式爬虫协同获取数据,利用多节点带宽减少对单机节点的压力, 同时提高了爬虫的效率

生活像巧克力,你永远不知道下一颗是什么颜色

在技术架构稳定, 产品输出正常的状态下, 公司内部资金链出现了断裂, 导致业务开展困难。 创业公司所面临的处境你永远不要高估,能活下去是第一要务, 其他的都是华而不实的外衣, X公司所遇到的处境着实令人可惜, 也许只要再多努力一把, 就可以起死回生。连续经历了两家失败的创业公司, 深有感触,都说成功不可复制, 但是失败一定是可以学习的, 今天我想再总结下失败的原因:

  1. 业务模式线太多,不够专注
  2. 无论什么样的业务都需要合法合规, 否则得不偿失
  3. 人员管理有些松散,一切以业务驱动的方式快跑, 但是没有考虑到内部的效率和费用的优化

Anyway,又失业了

一直希望自己在一家创业公司发挥自己最大的价值,做成功一件事情, 走向财务自由。 但是随着年龄越来越大, 似乎也变得有点越来越惶恐, 是继续放手一博继续创业, 做自己喜欢的事情, 追求自己的梦想? 还是进入一家稳定的大公司, 对自己的妻子和孩子负责, 有更多的时间可以陪家人?如果选择一个安稳的工作,可能会逐渐失去创业的动力, 一切求稳,人生会变得非常简单和无趣。 如果选择继续冒险创业, 有99%的概率失败,一无所有,风险会比较大。What do you think?

这不是开始的结束, 这是结束的开始。

kick the ball

两年前我和两个朋友一次聊到了物联网, 我们彼此都对这个新生事物充满了兴趣, 因为万物物联是一件非常神奇的事情,它会影响我们的生活方方面面,小到一个智能插座, 大到物流供应链, 都有应用的场景, 这个行业未来一定前途光明。

契机

我的合伙人在一次坐飞机时认识了一个做智能门锁公司的CEO 张工,聊的很投机,在经过了短暂的接触之后, 张工明确表示了想和我们合作开发智能家居产品,因为我们具备软件研发能力, 对方公司具备硬件研发能力, 优势互补, 双方合作应该会取得双赢。 当时我们还有各自的工作, 我们抽了一个周末讨论了之后就决定要出来创业。我们主要考虑的是首先可以和张工公司以项目的方式合作起来, 同时我们可以借机了解物联网市场, 同时积累物联网方面的开发技术, 一举多的, 所以我们很快就决定了要出来做这件事情。

历程

在决定了和张工合作之后, 我们同时思考了自己的创业方向, 初步定位在做物联网解决方案,因为我们不具有硬件研发能力,所以我们要做的就是集成市面上的硬件或者直接和硬件厂家合作, 我们负责开发软件产品,然后和硬件打包成一个解决方案。

和张工的合作起初谈的也是非常的顺利, 最后的合作方式是我们负责张工公司所有的软件开发工作, 张工负责给我们每月固定的一笔收入。

事实上, 越保险的事情越是不靠谱, 事后想想,这是一个最失败的合同。

在合作期间,我们一边帮助张工做好智能家居以及其他的软件开发工作, 同时也在不断的思考创业方向, 因为那段时间我和合伙人是住在一起的, 所以我们每天都会沟通创业的方向和机会,我们曾经设想过的解决方案有:

装修结局方案平台: 装修公司,设计师,用户可以在一个平台上公开透明的交流,实现三方最优智能装修方案
垂直领域的解决方案:养老院/美容院解决方案, 帮助特定的人群通过物联网的方式解决疑难问题
酒店智能化监控解决方案:帮助酒店解决能源管控的问题
以上更多的想法只是停留在了思想里,并没有真正的执行到位, 这也是给后续创业失败提供了导火索。

在经历了一年的合作之后,我们在查看合同的细则时,发现漏洞重重, 得出的结论是,我们为张工免费开发了很多软件项目, 同时由于在一些验收细节上没有定义清楚,导致了后续的收入分配出现争执,这是我们在一开始万万没有想到的。

后来经过深思熟虑决定自己出来创业,我们尝试了找了两个硬件合作伙伴,一个负责硬件PCB板设计, 一个负责硬件嵌入式开发, 直到这个时候,我们才意识到这才是创业的开始。

为了不使之前的工作全部白费, 我们把战略目标定位: 短期内面向酒店客户提供RCS解决方案。长期内做智能家居解决方案, 面向个人家庭和别墅。

然而,在实际操作的过程中,远非我们想象那般简单。首先RCS解决方案对酒店来说是个负担, 因为每年都会有维护费用;同时, RCU厂家也不倾向于和软件开发商合作, 和自己分一杯羹。

对于智能家居整体思路, 一开始我们是瞄准房地产开发商,因为有量, 并且是清一色复制实现即可,避免了个人家庭的客单价底和个性化需求带来的诸多人力花费。但是事实上房地产开发商要的并不是我们的这一套不成体系的解决方案, 他们要的是有自己的团队,可以自由把控发展方向和资金投入, 同时我们因为没有大型项目的实施方案, 对产品整体的稳定性没有太大的信心, 所以后来我们定位在别墅。 介于个人家庭和房地产开发商之间的一个群体, 有一定体量,并且也不会有太多的定制需求。

接着, 我们在实际操作的过程中,又碰到了更多的问题:

  1. 产品开发周期问题
  2. 前期垫资问题
  3. 装修问题
  4. 售后维护问题

对于装修问题和售后问题可以直接通过合作的方式来达到,但是对于开发周期长和垫资问题如何来填补?

思考

我们不缺理想和目标, 但是现实面前我们必须作出抉择。由于家庭各方面压力,加上我们并没有去融资,很多开销成本都是我们硬撑着,两年之后, 我们在经历了各种尝试, 找合作机会之后发现还是没有太大的成果, 于是我们放弃了继续创业下去的想法。

纵观这段经历, 我们的失败原因归纳有一下几点:

  1. 自身财力不够:物联网是重资产, 我们的个人能力无力支撑长期的硬件投入和项目垫资需求, 长久发展需要有资本的支持
  2. 市场能力不够:更多的依赖于一个人去谈判和接触, 另外两个合伙人参与的相对较少, 没有在这方面有自己的更多的思考
  3. 执行力: 在思考可能的创业方向时,缺少行之有效的快速验证方法和调研,停留在纸面上的想法居多, 有一些想法在开始的时候因为没有信心也就直接放弃了
  4. 过于理想化:从最开始创业坚持只做有持续长尾效应的工作,没有先考虑养家糊口的事情, 有点冒险
  5. 人脉资源短缺:创业的初衷想的是做有价值的解决方案,然后通过口碑宣传, 发展更多的客户。但是在做到那一步, 需要先解决从无到有的问题, 这一步却是最难迈的。
  6. 市场不成熟:智能家居对于个人家庭只是有个锦上添花的东西,不是刚性需求,消费者人群很狭窄,和工业物联网相比没有解决迫切的问题
  7. 定位有误:物联网解决方案是以个非常宽泛的想法, 在没有具体的落地项目开发经验之前,更多的只是空想

以上是我对第一次创业经历的简单总结, 对于每个创业者来说, 往前走一步都很艰难。在创业的路上,我们要做的是,努力向前迈进,同时不断抬头看路,修正改变,做最好的自己。共勉!

前言

架构,又名软件架构,是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。 架构描述语言(ADL)用于描述软件的体系架构。

在谈这个话题前, 首先回答一个问题, 前端需要架构吗?

架构从概念上包含三个部分, 一个是整体结构,另一个是个体,还有就是个体之间的关系。 本质上来讲, 只要复杂的软件系统就需要架构, 因为复杂度会带来“熵”,不利于项目整体的开发和维护,容易滋生潜在的问题。当然架构也不是银弹,在不同的软件体系里架构所做的是一个权衡, 在不同的方面做取舍,达到一个动态的平衡。那么对于前端来说,复杂度体现在哪些方面?

  • 页面多
  • 业务逻辑复杂
  • 终端类型多: 不同的浏览器内核,分辨率,ES规范支持度
  • 请求多:资源文件,异步数据,WebSocket等
  • 第三方的服务
  • 浏览器插件交互:截图,获取数据,网络代理等
  • 网络安全:XSS,CSRF,SQL注入

以上我只是列举了一部分内容,在现代化的大型开发项目中,大家可以看到前端的复杂度可能已经超过了后端的复杂度,所以说前端目前需要架构。

前端发展历程

  • 单web页面

    在这个时代页面所有的逻辑都放在一起,一个页面包括所有的JS/CSS/HTML, 甚至是后台代码,典型代表:ASP/JSP/PHP等

  • 优点:整体页面逻辑清晰,方便修改
  • 缺点:不利于多方协作开发
  • 逻辑展现结构分离

    随着页面逻辑越来越多,但页面已经无力维护,这时候需要迫切拆分样式(CSS)和逻辑(JS)、以及结构(HTML),并分别维护

  • 优点:分离关注点
  • 缺点:业务逻辑还是放在一起,不易维护
  • 组合和插件化

    业务逻辑变得越来越多,单个JS已经无法支撑,这个时候迫切需要对逻辑进行拆分,以适应复杂页面的需要。拆分的总体思路是提供一个基础的系统,对外扩展开放,对内修改关闭,就是常说的开闭原则。常见的做法有两种方式:

  • 提供一个Base基础类,然后基于Base类进行Compose扩展新功能, 如:TroopJS
  • 提供一个微内核,外围功能通过插件的方式注入,如:jQuery UI

优点:面向变化
缺点:无法体系化和规范化

  • AMD/CMD/UMD/MVC/MVVM/ES Module

    项目中外围功能越来越多,单纯的插件和组合方式已经难以满足业务的需求, 最明显的一个问题是首次加载的库依赖过大,另一个是项目如果对第三方有依赖,很难按照统一的规范来引入。所以在这个阶段出现了:

  • AMD:异步模块依赖加载,解决浏览器端模块加载和模块规范问题, 例如: RequireJS
  • CMD:通用模块依赖加载,用于服务端module加载, 例如:NodeJS
  • UMD:统一模块依赖加载,主要解决多端统一模块加载规范, 例如:Rhino/NodeJS/浏览器端用同一套规范
  • MVC:后端的经典架构模式, 拆分Model/View/Controller,职责模块分离。 例如:Backbone/Konckout
  • MVVM:在MVC的基础上去除了Controller层,增加了ViewModel层,主要解决Model和View变化响应的问题, 典型代表:AngularJS 1.0
  • ES Module: ES6自带模块加载器

优点: 模块拆分清晰,加载分明,外部依赖加载规范
缺点:每个模块的JS和CSS修改需要到统一的目录去修改,对于公用的模块加载还是会有冗余, 对于复杂项目无法快速拼装

  • 组件化

    组件化的发展起源于Facebook,由于Facebook页面Widget非常的多, 每个Widget加载都有相关的细粒度的依赖,所以Facebook提出了BigPipe的概念,把页面的每个部分分别作为一个独立的部分异步加载, 包括JS和CSS。随着项目的推进和不端规范化, 开源了React组件开发框架。React的优秀之处在于几个创新:VirtualDom,数据彻底分离出去,把JS/CSS/HTML当成一个组件处理。这样做的好处显而易见:

  • 页面按需渲染
  • 搭积木的方式构建
  • 不包含业务逻辑
  • 响应式变化

作为后起之秀的VueJS, 充分吸收了React的VirtualDom概念,并提供数据双向绑定机制, 通过依赖跟踪Check提高了脏检查的效率,同时在API层做到了精简,拨洋葱式的架构组合,在选择上灵活多样。

未来的发展趋势

  • 组件标准化: 随着WebComponents标准的建立和Polymer等优秀框架的实践,在前端的架构体系和标准化方面逐渐完善
  • 服务本地化:以Amazon Lambda服务为首的Serverless概念对于前端开发是一个大的变革,结合ServiceWorker打造PWA应用是一个应用趋势
  • 语言静态化:JS最为人诟病的是运行时异常, 通过引入类型系统做到在开发时异常检测,避免线上出现未知的运行时异常, 主要代表: TypeScript/Flow/Elm
  • 构建智能化:自动解析前端的资源文件,第三方的依赖并打包,不同环境的代码自动化部署、测试、集成,以及前端AI等技术的出现会在一定程度上会改变现有的前端开发流程
  • AR/VR:WebAssembly将会是的浏览器端能够负担更多的底层工作,对于内存管理更加高效,对于复杂高密度的工作放在前端执行增加了可能性, 典型的应用:VR/AR游戏,实时视频电话会议等

结语

前端的复杂性表现在各个方面,这里篇幅有限,介绍还不够细致。不过可以肯定的是,作为前端开发人员,已经远远不是会写JS代码这么简单,需要不断的参与到社区的学习中去,并加以实践,总结提炼出适合项目的架构方式, 提高自己开发和协作效率变得尤为重要。接下来,我会带领大家逐个学习前端的方方面面,体验前端开发的乐趣, 敬请期待

由于水平有限,有不当之处请批评指正,一起学习!

0%