Fork me on GitHub

ARTS-4

ARTS是由左耳朵耗子陈皓在极客时间专栏《左耳听风》中发起的一个每周学习打卡计划。

1
2
3
4
5
6
7
Algorithm:至少做一个 LeetCode 的算法题。主要为了编程训练和学习。

Review :阅读并点评至少一篇英文技术文章。主要为了学习英文,如果你英文不行,很难成为技术高手。

Tip:学习至少一个技术技巧。主要是为了总结和归纳你日常工作中所遇到的知识点。

Share:分享一篇有观点和思考的技术文章。主要为了输出你的影响力,能够输出你的价值观。

Algorithm(算法)

反转单链表

方法一:迭代

假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3

在遍历列表时,将当前节点的 next 指针改为指向前一个元素。由于节点没有引用其上一个节点,因此必须事先存储其前一个元素。在更改引用之前,还需要另一个指针来存储下一个节点。不要忘记在最后返回新的头引用!

1
2
3
4
5
6
7
8
9
10
11
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}

复杂度分析

  • 时间复杂度:O(n),假设 n 是列表的长度,时间复杂度是 O(n)。
  • 空间复杂度:O(1)。

方法二:递归

视频地址: https://www.youtube.com/watch?v=lnAhayckbqo

递归版本稍微复杂一些,其关键在于反向工作。假设列表的其余部分已经被反转,现在我该如何反转它前面的部分?

假设列表为:

1
2
3
4
5
6
7
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode p = reverseList(head.next);
head.next.next = head;
head.next = null;
return p;
}

复杂度分析

  • 时间复杂度:O(n),假设 nn 是列表的长度,那么时间复杂度为 O(n)。
  • 空间复杂度:O(n),由于使用递归,将会使用隐式栈空间。递归深度可能会达到 n 层。

分析:

  1. 感觉官方题解的递归确实有点难理解,将每一行的的执行结果都打印出来我才看出来到底做了什么操作。

    • 优点:相当于将原链表中的节点从后向前一个一个拆下来并按顺序放入新链表,原链表从后往前每拆一个节点,新链表p的尾部就加上这个被拆下的节点。
    • 缺点:
      1. 没有尾递归优化,链表节点数量大递归很深的情况下存在溢出危险
      2. 方法直接修改内存地址的指向,操作不直观。思路很好,但代码可读性较差(可能我太菜所以一下看不出来)
  2. 具体步骤分析:

    1. const p = reverseList(head.next);这一行代码中的p对于整个递归栈而言最终返回了原链表中最后一个节点的地址,也是反转后新链表的head

    2. head.next.next = head;
      

      这一行做的操作比较复杂。

      1. 递归每次退栈后时head相当于从后往前迭代原链表的每一个节点
      2. 实际上head.next已经是原链表的当前尾节点了,在递归上一次退栈过程中的head.next = null;已经将当前递归栈中head.next.next变为null。
      3. 同时head.next即原链表的当前尾节点和新链表p的尾节点是指向同一个内存地址的,也就是新旧链表的尾部此时在内存中是同一个地址。
      4. 看出来以上三点之后,可以得到head.next.next = head;同时也是p[尾节点].next = head,就是将当前节点head的地址添加到新链表p的尾部。这个操作将原链表的第n个节点放到了第n+1个节点的后面,所以仍然存在一点问题,就是循环引用。
    3. head.next = null;因为上一行执行完后实际上使 head.nexthead.next.next 变成了循环引用,所以需要将这个循环给释放掉,不然新链表的尾部也是一个存在相同的循环引用。因为此时的 head.next === p[在循环引用之前的末尾节点] (同时 head === p[在循环引用之前的末尾节点].next),即 head.nextp[在循环引用之前的末尾节点] 是指向同一个内存地址。所以这一行的操作就是在切断循环引用,切完之后实际上已经实现了当前末位节点的反转

    4. return p;每次递归退栈返回尾部添加了一个新节点的反转后链表

参考文章:

递归与迭代

Review(点评)

  1. 对自己诚实: 真正想要的是什么。
  2. 始终如一地设计并过上理想的一天: 设计你的日常生活,这样你就可以将所有时间(如果不是大部分)花在你真正重视和关心的事情上。
  3. 不要迷失在“成功”的迷宫中,目标不是目的,达到目标后,树立下个目标。

为什么大多数人永远不会得到他们想要的

实现梦想的第一步:诚实守信

尽管人们欺骗别人,但我们对自己说谎最多。我们每天都骗自己。

诚实是情绪化的 - 这就是我们撒谎的原因。我们躲避情绪。我们不想变得脆弱。我们不想被拒绝。我们不想失败。我们不想错。相反,我们把我们的情绪压低并忽视它们 - 这是我们的危险。

要开始你的情感发展之旅,你必须开始对自己更加诚实。

如果你不追求你真正想要的东西,你永远不会感到成功。

实现梦想的第二步:始终如一地设计并过上理想的一天

一旦你开始诚实地对待自己真正想要的东西,就必须停止拖延。

你必须开始设计你的一天,以配合你的梦想。你过着24小时的生活。24小时如何使用这些决定了你生活中的“成功”。

您需要最大限度地利用您在最高优先级上花费的时间。

实现梦想的第三步:不要迷失在“成功”的迷宫中

目标不是目的。他们是手段。一旦达到目标,就需要另一个目标。目标是自我改善的工具。它们是组织生活以实现梦想的方法。他们永远不应该停止。

每击中一个目标,你的信心就会增强。随着你的信心增加,你的想象力和更大目标的能力也会增加。因此,实现目标不应该结束你的未来,它应该扩展你的未来。

如果你过度依附于击中目标所带来的状态,那么你已经用完了未来,现在已经过去了。

结论

实现自己的梦想并实现“成功”是一项艰难但值得追求的目标。

它始于对自己诚实开始和结束。

这可能很困难,因为我们是社交和情感生物。我们不想让其他人失望。我们不想完全诚实地告诉我们我们是谁或我们想要什么。相反,我们埋葬了我们的情感,过着安静的生活。

不要这样做。

不要自欺欺人。

开始告诉周围的人你真正想要的东西。保留支持你的人。放弃那些试图让你留在原地的人。

然后,设计你的日常生活,这样你就可以将所有时间(如果不是大部分)花在你真正重视和关心的事情上

当你成功时,不要迷路。

如果你不知道自己到底是谁 - 那么成功就会误导你。你要么过度地依附于你所开发的特定状态,要么迷失在其他人的议程(即“机会”)的迷宫中。

一直以来,你需要不断地与自己保持联系,并对自己诚实。老实说,你需要对出现的机会更快地说“不”。

仅仅因为某件事是一个很好的机会并不意味着你应该这样做。一切都有成本。时间是最大的成本。

当你开始对最高的自我完全诚实时,就会立即开始发生惊人的事情。

成功将会发生。必须成功。但它只有在你开始过你想要的生活时才会发生,而不是在成功的时候迷失。

Tip(技巧)

使用Jenkins Theme美化jenkins

Jenkins-Theme生成jenkins定制主题

Share(分享)

使用Flasgger让Python集成Swagger(翻译)

Jenkins Theme生成jenkins定制主题

原文地址: https://i4t.com/3720.html

jenkins的默认界面实在是太丑了,可以使用Jenkins Theme生成定制主题进行美化。

效果图

image_1d97cfonfpkielp1rdl1u2r1mju37.png-127kB

Jenkins默认界面比较丑,视觉容易疲劳,这时候就需要我们更换一个主题。让我们的Jenkins美观一些

安装步骤

首先需要我们打开生成css主题的地址:http://afonsof.com/jenkins-material-theme/

Select your color

选择一个你喜欢的主题颜色。

Choose your company logo

上传你自定义的公司logo。

点击“↓DOWNLOAD TOUR THEME!”

上传logo完成之后,按钮会变更为下载按钮,点击下载到本地。

1.选择主题颜色

2.选择公司logo,然后我们点击下载css

3.Jenkins 配置

安装simple theme插件

在主菜单中选择系统管理->管理插件

安装完插件我们点击 系统管理–>系统设置找到配置Theme的地方

Theme获取css文件有2种方式,第一种我们上传到nginx站点访问,第二种上传到Jenkins目录

第一种可以直接写http://down.i4t.com/jenkins-material-theme.css进行测试

1
http://down.i4t.com/jenkins-material-theme.css

第二种

将之前下载的css文件放置到${Jenkins_HOME}/userContent/material/

没有material文件夹的可以自己创建,其他名字也是可以的。

${Jenkins_HOME}这里是Jenkins默认目录,不修改家目录的情况下在/root/.jenkins

!

4.预览演示

我们配置好css地址之后,点击保存

java程序员必备软件和工具(原创)

工欲善其事,必先利其器

—《论语》

硬件

  • 硬件是所有软件的基础,是团队合作的基础,不希望大家开发的时候总是在抱怨这个卡、那个慢
  • 推荐还没有经济实力情况下使用黑苹果,有经济实力后购买原生苹果产品
  • 相关硬件配置推荐:点击我

MacBook Pro (16G+)

生产力工具

mac系统牛批🐂

4k显示器

mac的好伴侣

软件

Chrome

地球上最好用的浏览器

IntelliJ IDEA

宇宙最强 java ide

###Postman

接口测试必备

Shadowsocks

不会翻墙的程序员不是好程序员 👨🏻‍💻

Git

版本控制龙头老大

钉钉

工作交流

Sourcetree

Windows 和Mac OS X 下免费的 Git 和Hg客户端,拥有可视化界面,使用方便、易上手。(虽然我通常是用 idea 自带的 git 工具)

jira

针对缺陷管理、任务追踪和项目管理的商业性应用软件

开发必备,再也不会记不住要改哪些bug了。(每天不是在写bug,就是在修bug的路上🤪)

onfluence

Confluence是一个专业的企业知识管理与协同软件,也可以用于构建企业wiki。使用简单,但它强大的编辑和站点管理特征能够帮助团队成员之间共享信息、文档协作、集体讨论,信息推送。

没有积累的团队不是好团队

网站

Google

google大法好

Github

程序员的后花园,值得每日一逛

你可能会忽略的 Git 提交规范

原文地址: http://blog.didispace.com/git-commit-specification/

一直是 ESLint 的忠实用户,深知规范的重要性。然而,在新项目交接中,我被 Git Commit 规范逼疯了。才意识到自己的疏忽,于是便有了一探究竟的想法。

一、为什么需要规范?

无规矩不成方圆,编程也一样。

如果你有一个项目,从始至终都是自己写,那么你想怎么写都可以,没有人可以干预你。可是如果在团队协作中,大家都张扬个性,那么代码将会是一团糟,好好的项目就被糟践了。不管是开发还是日后维护,都将是灾难。

这时候,有人提出了何不统一标准,大家都按照这个标准来。于是 ESLintJSHint 等代码工具如雨后春笋般涌现,成为了项目构建的必备良品。

Git Commit 规范可能并没有那么夸张,但如果你在版本回退的时候看到一大段糟心的 Commit,恐怕会懊恼不已吧。所以,严格遵守规范,利人利己。

二、具体规则

先来看看公式:

1
<type>(<scope>): <subject>
  • type
    • 用于说明 commit 的类别,只允许使用下面7个标识。
1
2
3
4
5
6
7
feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变动)
refactor:重构(即不是新增功能,也不是修改bug的代码变动)
test:增加测试
chore:构建过程或辅助工具的变动
  • scope
    • 用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。
  • subject
    • 是 commit 目的的简短描述,不超过50个字符。
1
2
3
1. 以动词开头,使用第一人称现在时,比如change,而不是changed或changes
2. 第一个字母小写
3. 结尾不加句号(.)

规范参考自阮一峰老师的文章:Commit message 和 Change log 编写指南

三、异常处理

我们先来看看这个异常提醒:

1
2
INVALID COMMIT MSG: does not match "<type>(<scope>): <subject>" !
jartto:fix bug

这里之所以报出这个警告,是因为我的提交出现了两个问题:
其一,使用了规范外的关键字;
其二,很细节的问题,jartto:后少了空格;

这时候我才回忆起来,当时提交一直失败,情急之下直接强制提交,所以以后的提交都会抱出这个异常。大致意思就是:

阅读更多...

经济持续下行,这些行业很抗风险,最后一条切记

原文地址: https://zhuanlan.zhihu.com/p/58262945

思考🤔: 学习,学习再学习

聪明的人会不断学习新知识新技能,加强自己的综合竞争力,在沉默期补充能量做准备,爆发期积极进取,总是让自己立于不败之地

01 — 经济持续下行

中国自1978年改革开放以来,经济持续了四十多年的高速增长。随着人口红利的逐步丧失和欧美消费市场的低迷,中国经济呈整体下行的趋势。这个持续时间大概半个世纪的高速增长在中国历史上前所未有,以后也可能不会再有了。

img


前几天接到老同学L的电话,说他老板嫌利润太低要把店给关了,并遣散所有员工,L的老婆刚生孩子,父母又年迈,正当用钱之时,L在言语中不免时有哽咽。
L一直从事高端运动自行车的销售工作,在自己的努力下,收入从七八年前的月薪3000,后来涨到5000-6000,再到2018年开始月入万元,可谓一路水涨船高。去年和林先生小聚时,他说干到2020年,存个二十来万就回老家。没想过刚过年就发生这种变故,L一时也不知何去何从。

img


欢子在深圳从事国际物流工作多年,他凭借自己的努力,高峰时每个月能赚个12k左右的收入,由于对未来收入看好,去年还贷款买了台本田思域,月供三千多元。

不料2018年国际物流业务量骤降,每个月收入除掉还贷房租已经难以维持日常生活,再三考虑后放弃了奋斗多年的深圳,回家跟着老爸做市政自来水工程。

img


李工,C语言高级开发工程师,一直在广州某打卡机担任研发部主管工作,年薪20万。结果阿里巴巴强势插入这个行业,搞了个钉钉,2018年公司业务断崖式下跌,老板直接心肌梗塞挂了。长达半年发不出工资后,李工无奈选择离职另谋他就。

img


刘先生一直在香港打工,顺带做化妆品代购,干了几年有了三十万的存款。2018年刘先生在深圳龙岗开了一家烧烤清吧,也因为经济不景气消费人群骤减,半年后转让出去了。

img


布满阴霾中国经济已经开始影响到身边的很多人,投资失败,失业的消息不绝于耳。多少人上有老下有小还背负着房贷车贷,突然失去经济来源这种压力可想而知。但是经济下行并非影响到所有人,经济本身就是波动的,经济过热和回冷本就是一种循环,很多行业本身就很抗风险,只有那些可替代性非常高的工作才会受到很大的影响。

02 — 这些行业很抗风险

  • 教师、医生、公务员等体制内工作,短期受到经济冲击的影响几乎没有,唯一的的缺点就是体制内工作单调乏味,如温水煮青蛙,有跟社会脱节的可能。

img

  • 技术型工作,有人说技术型工作吃不饱饿不死,食之乏味弃之可惜,但正是因为这一点,技术型工作才能抵抗经济风险,不论世界怎么变化,去做一般人做不来的事总是更有竞争力。最近疯传互联网开始大裁员,但有公司倒闭,也就有新公司创立,新公司也需要程序员来做事,社会上对技术人员的招聘并没有明显减少。上面提到的李工,经济下行对他来说就是换一份工作重新开始而已,比失业好多了。

img

  • 创业,危机时刻也是个创业孵化器,对于有准备的人来说,平常时期各方面都争不过大公司,只有被吊打的份。但是经济下行时,一来政府会鼓励创业,二来招人比较容易。

img

03 — 学习能让自己立于不败之地

经济过热的时候,学历和技能都不那么重要,寅吃卯粮让整个世界歌舞升平,读书无用论甚嚣尘上,技术工人也遭受歧视。

待热潮褪去,经济下行,哀鸿遍野,为大家挖掘资源的老板们一个个倒下,越来越多的人开始独自面对这个江湖,才发现自己手无寸铁,竟然无缚鸡之力。而聪明的人会不断学习新知识新技能,加强自己的综合竞争力,在沉默期补充能量做准备,爆发期积极进取,总是让自己立于不败之地。

思考 1: 一些思考🤔(2019.09.8)

封闭系统一定会崩塌,通过熵增理论,如果不从外部注入能量,封闭系统是维持不下去的

北京存在一个天然的基因筛选过程,能在北京活下去需要有一定的经济条件,有钱的人会相互结合变得更有钱,而且通过筛选有钱人小孩基因会越来越优良,颜值也越高。

颜值即正义

现在在国企,食堂是一家公司承保的,因为饭菜难吃,已经换过一家了餐饮公司了,现在这家饭菜变也越来越难吃了,由此可见垄断绝对不是好事

2018-2019 大环境越来越差。

房价过高,工资水平却没涨多少,我觉得越来越多年轻人会选择租房而不是买房。租房市场也是被几家公司垄断,房租高,还需要压一付三,压力比较大,还需要签一年的合同,而这会阻遏创新和人员流动。

先吃饱饭🍚,再谈理想

只有变强才能活下去,不然只能滚回老家 (继承老家的八十多亩地😼)

磨炼技术,紧跟潮流

好的团队是非常重要的

经济不好 -> 裁员 -> 没钱 -> 不消费 -> 裁员

娱乐至死,哪吒之魔童降世的票房火爆有些像经济危机时国外的电影行业繁荣

软件,机器,人工智能取代人,如果生存

使用Flasgger让Python集成Swagger(翻译)

原作者: Bruno Rocha

原文地址: Flasgger - API playground with Flask and Swagger UI

翻译: 高行行

代码地址: python-flasgger

1. Swagger是什么?

Swagger是RESTful API简单而强大的代表。凭借全球最大的API工具生态系统和数千名开发人员。几乎所有现代编程语言和部署环境中都支持Swagger。使用支持 Swagger 的API,您可以获得交互式文档,客户端SDK生成和可见性。

2. Swagger UI是什么?

Swagger UI是一个HTML,Javascript和CSS无依赖关系集合,可以从符合Swagger规范的API动态生成漂亮的文档和沙箱。由于Swagger UI没有依赖关系,因此你可以在任何服务器环境或本地计算机上托管它。跳转到Swagger UI 在线演示

3. Flask什么?

Flask是基于Werkzeug,Jinja 2的Python微框架。为什么它非常棒?因为它简单但功能强大,沟通代码更方便!

1
2
3
4
5
6
7
8
9
from flask import Flask, jsonify, request
app = Flask(__name__)

@app.route('my_awesome_api', methods=['POST'])
def my_awesome_endpoint():
data = request.json
return jsonify(data=data, meta={"status": "ok"})

app.run()

运行上面的脚本,然后就可以开始发送请求到API

1
2
3
4
5
curl -XPOST http://localhost:5000/my_awesome_api -d '{"python": "is awesome"}'
{
"data": {"python": "is awesome"},
"meta": {"status": "ok"}
}

4. Flasgger是什么?

Flasgger是Flask的扩展,用于帮助创建Flask API,其中包含由SwaggerUI提供支持的文档和调试工具。你可以使用YAML文件定义API结构,Flasgger会为你创建所有规范,你可以使用相同的模式来验证数据。

GITHUB REPO: https://github.com/rochacbruno/flasgger

5. 安装

1
pip install flasgger

6. 创建应用

您可以将API规范直接放在 docstrings 中

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
import random
from flask import Flask, jsonify, request
from flasgger import Swagger

app = Flask(__name__)
Swagger(app)

@app.route('/api/<string:language>/', methods=['GET'])
def index(language):
"""
This is the language awesomeness API
Call this api passing a language name and get back its features
---
tags:
- Awesomeness Language API
parameters:
- name: language
in: path
type: string
required: true
description: The language name
- name: size
in: query
type: integer
description: size of awesomeness
responses:
500:
description: Error The language is not awesome!
200:
description: A language with its awesomeness
schema:
id: awesome
properties:
language:
type: string
description: The language name
default: Lua
features:
type: array
description: The awesomeness list
items:
type: string
default: ["perfect", "simple", "lovely"]

"""

language = language.lower().strip()
features = [
"awesome", "great", "dynamic",
"simple", "powerful", "amazing",
"perfect", "beauty", "lovely"
]
size = int(request.args.get('size', 1))
if language in ['php', 'vb', 'visualbasic', 'actionscript']:
return "An error occurred, invalid language for awesomeness", 500
return jsonify(
language=language,
features=random.sample(features, size)
)


app.run(debug=True)

7. 运行

现在运行应用程序并访问 http://localhost:5000/apidocs/index.html 将会跳转到 Swagger UI 界面

启动效果

Swagger 测试效果

注意: 可以在配置中更改所有默认URL。

也可以使用单独的文件进行规范

阅读更多...
  • Copyrights © 2015-2023 高行行
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信