Fork me on GitHub

合并小文件——一个算法在实际程序开发中应用的例子

源文地址 合并小文件——一个算法在实际程序开发中应用的例子

现在的学生爱说算法对实际项目开发没多大作用,其实这是错误的——现在就园子里看到的一个讨论,提出一个我的方案,作为为一部分朋友举例说明“程序=数据结构+算法”这个不变的道理

讨论源于此http://space.cnblogs.com/question/2616/

讨论中,lexus朋友还是打算将小文件选择性合并,于是有了新讨论http://space.cnblogs.com/question/2630/

简单说一下算法的要求:当两个文件的大小(KB)小于某个设定值时,两个文件就合并,这样一直合并下去。

有朋友提出用排序来解决,我觉得开销太大,排序一次时间O(nlogn),如果每次都排序则复杂度高达O((n^2)logn),不值。

也有朋友提出使用简单插入,那么复杂度是O(n^2)。

“合并文件”,让我想起一道经典的ACM题目——“合并果子”,合并两个文件可以采用贪心,类似Huffman算法,这里合并多个文件和合并两个文件是一样的。

传统Huffman算法的时间复杂度是O(n^2),技巧不好的话会更多,通常的改进办法是使用堆进行优化。

关于堆(Heap),不了解的朋友可以参考一下数据结构的基础书籍

多余背景资料我在这里就不多做介绍了,下面说下我对这个问题的解决方案:

注:下文中每次对堆进行操作后都进行堆维护,不再赘述。

1
2
3
4
5
6
7
8
9
10
11
0.将所有文件建立小顶堆,并且建立一个足够大的缓冲区;

1.设缓冲区内文件总大小是buffer,堆顶文件大小是top;

2.查看top

if (buffer + top <= max_file_size) 则将堆顶弹出到缓冲区

else 将缓冲区内文件合并,新文件压入堆中

3.循环2,直到缓冲区为空,且top >= max_file_size

实际上这里的堆就是个优先队列(Priority Queue),STL中的PQ就是用堆实现的。

分析一下整个算法的性能:

文件总数为n

建立堆需要O(nlogn)

遍历所有文件需要O(n),这个过程中需要进行堆维护,每次O(logn)

所以总的时间复杂度是O(nlogn),和用堆改进的Huffman算法是一样的。

再看看空间需求:

直接算最坏的需求,如果所有文件都足够小,能把所有文件合并在一起,那么缓冲区需要n的长度,所以最坏需要n辅助空间。

以上是我自己能想到最快的算法。

从这个例子看出,在实际应用中,数据结构和算法依然占据核心的地位不会动摇,打好了基础才能做出好的程序。

面对STL,面对java,面对.NET Framework Library,这些琳琅满目的库,我们可以方便地应用各种数据结构和算法,但是如果我们对他们本身的实现没有一定的了解,有怎么能知道在不同的场合下什么选择才合适呢?

所以我还是坚信“程序=数据结构+算法”这个道理是恒定不变的真理。

Git 自救指南:这些坑你都跳得出吗?

原文地址 https://mp.weixin.qq.com/s/tiyaL_ikHlmq97Eq3gD4IA

作为国内领先的研发管理解决方案供应商,CODING 一直致力于在国内普及 git 的使用,为软件研发提供更高效率。本文节选自 Katie Sylor-Miller 在日常工作中所遇到过的让他很头疼的 git 相关问题,并整理了相应的应对措施,在这里分享给正在学习如何使用 git 的同学们。当然这些应对措施并不是唯一的,可能你会有其他更好的应对方法,这也恰恰是 git 这套版本控制系统强大的地方。

01

/ 我刚刚好像搞错了一个很重要的东西,

但是 git 有个神奇的时间机器能帮我复原! /

reflog 是一个非常实用的命令,你可以使用这个命令去找回无意间删除的代码,或者去掉一些刚刚添加的却把仓库里的代码弄坏的内容。同时也可以拯救一下失败的 merge,或者仅仅是为了回退到之前的版本。

02

/ 我 commit 完才想起来

还有一处小地方要修改! /

当我 commit 完然后跑测试的时候,经常突然发现忘了在等于号前面加空格。虽然可以把修改过的代码再重新 commit 一下,然后 rebase -i 将两次揉在一起,不过上面的方法会比较快。

03

/ 我要改一下上一个 commit message! /

当你们组对 commit message 有格式要求时,或者当你忘了中英文间要加空格,这个命令能救你狗命。

04

/ 我不小心把本应在新分支上的内容

commit 到 master 了! /

阅读更多...

【TED演讲】20岁到30岁,是你最不可挥霍的光阴(T君)

视频地址 【TED演讲】20岁到30岁,是你最不可挥霍的光阴(T君)

二十多岁应如何度过?讲者Meg Jay是一位资深心理治疗师,她想对年轻的你们说:决定你人生的不是命运,而是你做的选择。

蜉蝣一夕 总结

30岁不是新的20岁,所以把握好你的成年时期吧
积累一些身份资本,利用你的微弱联系
并且选择你的家庭
别被你不知道或没做的事定义了,你现在决定你生命的去向。

吴怜明 总结

1 二十几岁是学习的另一个高峰期,是最好的补足自己的时候

2 想要完成一件事情,最需要的是一个计划以及时间的紧迫感

3 千禧年后的中年危机,是在能不能发现自己的职业是不是自己想要的

4 努力积累身份资本,为自己做出投资

5 好好的利用微弱的连接,去选择你的朋友、同事甚至家人

6 别被不知道的事、没做的事情给定义下来,你当下的每一个行为都决定你生命的走向

鸶颐 总结

种一棵树最好的时间是十年前,其次就是现在。
——送给给评论里“已经挥霍完了”的朋友们

《the defining decade》演讲者书籍

20岁,光阴不再来

虎皮驴 豆瓣书评

两千多年前孔子就就教育人们,说三十而立。但是因为孔子的言论都在140个字以内,他也没有说说三十如何而立。两千年以后的今天,一美国的的心理学家Meg Jay写了一本书,就是告诉二十多岁的年轻人,三十如何而立。

书的内容分为了三个章节,第一章是工作,也是三十而立的根本,二十岁你应该开始你的事业而不是等;第二章是爱情,这个是整个人生的命题,是未来整个人生是否幸福的根基;第三章是身体,主要是谈谈二十多岁的人,大脑还在发育,还有机会建立自己稳固完整的脑结构,也处于身体机能最好的时候,适合生育。整本书以作者所接收的典型的”病人“或者说二十岁的求助者来作为案例进行分析,而每个案例都有比较详实的介绍,很容易让我这个也恰好处在二十多岁的人找到同龄人的影子,有的时候感觉那些案例就是自己的一个缩影。从这些案例中也可以看出,二十多岁,大家其实都在面临着同样的问题。刚刚踏入社会,没了作业,考试,课堂和同学,生活似乎真正开始了,但似乎一个模糊的未来也迎面而来。面对事业,应该如何起步,面对爱情,我们应该如何抉择。没有人来告诉你,指导你。如果你学英语,有千千万万的补习班、资料、网站以千千万万的形式喝方法告诉你如何学英语,但是如何开始你真正的生活,没人告诉你。如果你想创业,李开复们,薛蛮子们,甚至各行各业的大拿们都能跳出来告诉你,”年轻人,我看你骨骼惊奇,是个创业的好材料啊。”但是事实也并非如此,前方一片模糊的未来似乎给励志书,成功学,人生导师们,职业规划师们提供了一个庞大的市场,但是并没有给二十岁的年轻人提供一个真正明晰的目标。

这本书更多的是在心理层面的指导,也就是更多的让二十多岁的年轻人指导自己的内心是什么,而不是让励志故事来刺激你的大脑皮层。那没用。励志故事终究是别人的故事,看看而已。那些励志故事本身其实和火影忍者,海贼王没有什么本质的区别,只是让读者更热血而已。但热血过后总归是要回到现实中,重新面对那一团白雾的未来。这本书并不是给读者提供一个清晰的路程,它更多的是再告诉你,冷静下来,去做一些事情,去爱一个人,去选择一个家庭。这才是二十多岁的人生的本来模样,把二十多岁粉饰成一个无所不能,生命无限,机会千万的年龄,可能是顺应市场或这个浮躁的社会,而并不是真正的顺应二十岁年轻人的真正需求。

书本身的优缺点还是很明显的。本书侧重的是案例分析,书中的一些案例都是作者十几年来接触的二十多岁的年轻人,他们有各种各样这个年龄段特有的问题。这些问题涉及工作,爱情和身体。同时也有一些二十多岁年轻人特有的心态。比方说,工作不重要,因为我要在工作中学习,所以可以无限制的跳槽;爱谁不重要,恋爱本来就是一个很刺激的事,趁年轻应该多折腾折腾;身体也无所谓,现在科技发达了,医学进步了,寿命长了,三十岁才是正当年。这本书就是用种种活生生的案例来解释这些看上去成立的想法,其实并不成立。二十岁,需要的是冷静和努力,而不是一味的好高骛远。

而书的缺点也正是因为案例分析。书提到那些年轻人的例子,并不是简单的叙述,而是占有很长篇幅的对话记录。这让书本身也显得冗长。本来可以更深入的从心理层面探讨一下二十岁这个重要却很少被人提及的话题,但是因为太多案例细节的叙述,让整本书的内容有些稀释。另外,书中提及的一些心理学的实验,也在其他有关心理学的书中提到过,没有什么新意。

略去这些缺点不提,这本书提供了一个心平气和的态度来解决二十岁人的问题。实在是难得。用两句最近看到的话来谈谈我对二十至三十岁这十年的理解。

“不要急,不要等”

这句话出自一豆瓣的日记(http://www.douban.com/note/240434549/)。虽然只有六个字,但我觉得是一个良好心态的体现。这个商业的社会灌输给了年轻人太多的错误观念。每个人都信奉年轻无极限而很少人去静下心来。静心也不是等待,而是踏踏实实的做事。去做事,无论什么,不要觉得自己的生命有无限的可能性就不去选择,害怕选择了一个而失去其他千千万万的可能。年轻人需要的就是去做事,无论什么事情。只要去做,只要有了开端就会有一条路慢慢的铺开,通向一个美好的未来。

年轻的时候,我们总听到太多的生硬告诉我们你应该怎么做,或者别人都在做什么。这很容易让刚刚起航的我们不知所措。我们应该学会的是运用自己的大脑,运用自己的学识和思想,而不是去听别人让你怎么做。深思熟虑,为自己的人生负责。人生只有一次,二十岁是一个真正的开端,人生应该怎么过,选择权到这个时候才真正到了我们自己的手里。我们有能力也有责任来思考未来的人生。慎重选择自己的事业和家庭。这两样几乎就是我们人生的全部,无论伟大与平凡,事业和家庭永远是一个人一生的主题。无论是征服世界还是清粥小菜平淡一生,都属于事业和家庭。而二十几岁,是我们开始选择并位置奋斗的最好开端。正如书中的一个比喻一样。飞机从纽约飞向洛杉矶,如果在纽约稍稍调整一下飞行的角度,坚持下去,就会到达洛杉矶。如果对着西雅图的方向,等到了西雅图再飞往洛杉矶,那就需要更多的时间和燃料。所以,时日无多,找好角度,稳定心态,赶紧上路。

“The slower you go, the faster you get there.”

这是书中的一句话。与“不要急,不要等”基本是一个意思。静下心来,从二十岁开始我们真正的人生。慢慢走,终究功德圆满。

【TEDx演讲】结束拖延

视频地址 【TEDx演讲】结束拖延

拖延症几乎是每个人都有的问题,停止拖延的方法也不少,但能不能坚持下来也是拖延的一大问题。拖延,更像是一种态度的问题,也许只需要五个步骤,转换自己的态度,就能一步步结束拖延,提高工作效率。

略小方 总结

“穆尔蒂的正念元认知意义的方法”的五条准则:

  • 1 设定目标

    设立一个明确且清晰的目标

  • 2 保持乐观

    执行计划期间让自己充满正能量

  • 3 认识并反省自己的情绪

    在一天的结尾扪心自问,是否因为进步或者努力而感到心满意足/或一事无成时让自己了解内心的愧疚和焦躁(自我提醒);

  • 4 学会感恩

    无论做了很多,很少,或什么也没做,都要抽时间来学习感恩,感激自己有追梦的能力,向自己的目标努力

  • 5 记录每一天

    写反思日记

不要重视结果和目标,要不以物喜不以己悲(°ー°〃)

取个卵名真麻烦总结

拖延症治愈秘诀:专注眼前,别想后果。
拖延症治愈行为准则:
1:订立一个清晰的目标计划。在实施目标计划的时候拒绝一切分心的东西,比如手机、电脑、BALABALA。
2:保持计划期间正能量,阻止负面情绪和思考。面对并接受自己的错误,给自己改正的机会,而不是自暴自弃。
3:每晚事毕后自省。让自己主动意识到面对工作,努力和进步带来的快感,或者逃避工作、学习导致失败而引起的悔恨和内疚。这能让自己直观感受到面对和逃避带来的不同心境。
4:学会感恩。感恩自己四肢健全、有头有脑,能为一个目标去努力。感恩自己有机会接受某种教育或得到某项工作。(如果你有宗教信仰,你可以把努力当做对神的奉献。)
5:反思日记。记录一些自己的情绪状态变化,弄明白自己为什么会发生这些变化,更好的了解自己。
最后总结:不要老想着我花了时间去做这件事,结果却失败了会怎样。人的精力有限,当你专注于思考后果,你就没办法做好眼前的事。
昨天看瞎看有句话我觉得对我这个拖延症有用
老大爷:凡人皆有一死,与其等死不如找死。
旁白:都是死有什么区别。
老大爷:区别就是怎么活。

springboot 使用log4jdbc打印mybatis的sql和Jpa的sql语句运行情况

原文地址 spring boot 使用log4jdbc打印mybatis的sql和Jpa的sql语句运行情况

只需要相对于原来的项目修改两步

1.加入引用

1
2
3
4
5
6
<!--打印sql-->
<dependency>
<groupId>com.googlecode.log4jdbc</groupId>
<artifactId>log4jdbc</artifactId>
<version>1.2</version>
</dependency>

2.appliaction.properties,修改 driver 驱动和 url 数据源地址,重启项目即可

1
2
3
4
5
6
7
# 修改前
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=UTF-8

# 修改后
spring.datasource.driver-class-name=net.sf.log4jdbc.DriverSpy
spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=UTF-8

插件破解和实现本地/远程热部署教程

原文地址 微服务开发神器–JRebel 插件破解和实现本地/远程热部署教程(IntelliJ IDEA版)

为什么要用热部署?如果你公司使用微服务开发,你使用了一段时间的jenkins集成开发部署,你会发现即使有了这一套集成开发环境,假如我让你改个变量…你就需要跑一次jenkins,麻烦倒不麻烦,主要是花费太长的时间,所以开发阶段用远程服务热部署会更加方便和前端的对接,这也是这篇文章着重说的一点。

IntelliJ IDEA的JRebel插件包括JRebel代理并帮助您自动生成JRebel配置。它通过单击为应用程序和服务器启用JRebel,并改进了IDE中的调试支持。

这篇文章用英文来写(滑稽),希望你能看懂(滑稽)。

ok, let`s go

it can support many IDE tools that below:

img

1. Installation

1.1 Open the IntelliJ IDEA Settings
1.2. Select Plugins from the sections menu.
1.3. Press Browse plugin repositories… and locate the JRebel plugin.

img

1.4. restart IntelliJ IDEA

2. Activation

An excellent plugin is offen not free, and this is no exception.But i cant to teach you to buy it, of course that is the best way to get it, i will tall you how to crack this plugin.

2.1 open the JRebel control panel

img

you just need to fill in the infomation in these two boxes.

Filled in the first box is http://139.199.89.239:1008/d6bbb34d-84c4-4214-907e-26fc52f8e1b8 Filled in the second box is your email

Node: If the first box prompt expire, you can change to a uuid after the url.

OK, it is done when you click OK.

2.2 Change working model

if you just complete the first step, you also need to set this setting. Because in the case of working online, Exception will be detected at any time,(Will be detected as pirated).So follow me down:

![img](data:image/svg+xml;utf8,)

After that, you will see it becomes like this:

![img](data:image/svg+xml;utf8,)

OK, this is a success.

阅读更多...

git tag 发布项目打tag

// 命令格式
git tag -a 标签名 -m “附注信息”

// 示例
git tag -a v0.1.0 -m “完成了文章a和文章b的撰写,耗费时间2h,感觉棒棒的!”

git push origin v0.1.0

前言

最近使用git来管理一个项目,到达一定阶段后,需要将稳定的代码发布成一个版本,经过查找资料发现git的标签操作刚好满足我的要求,所以记录下来,方便以后是使用查找。

用途

标签可以针对某一时间点的版本做标记,常用于版本发布,这恰恰是我所需要的功能,将本地标签推送到Github上即发布了一个Release版本,下载和查看非常方便。

标签分类

git标签分为两种类型:轻量标签和附注标签。轻量标签是指向提交对象的引用,附注标签则是仓库中的一个独立对象,建议使用附注标签,日后还可以查看标签信息。

创建标签

  • 创建轻量标签

$ git tag v0.2.0 -light

解释:创建轻量标签不需要传递参数,直接指定标签名称即可。

  • 创建附注标签

$ git tag -a v0.1.0 -m “release 0.1.0 version”

解释:创建附注标签时,参数-a即annotated的缩写,指定标签类型,后附标签名。参数m指定标签说明,说明信息会保存在标签对象中。

查看标签

  • 列出当前仓库的所有标签

    $ git tag

  • 列出符合模式的标签

    $ git tag -l ‘v0.1.*’

  • 查看标签版本信息

    $ git show v0.1.0

  • 切换标签
    切换标签与切换分支命令相同

    $ git checkout [tagname]

    解释:切换标签后处于一个空的分支上,即”You are in ‘detached HEAD’ state.”

删除标签

  • 误打或需要修改标签时,需要先将标签删除,再打新标签

    $ git tag -d v0.1.2

    解释:参数-d即delete的缩写,意为删除其后指定的标签。

补打标签

  • 给指定的commit打标签

    $ git tag -a v0.1.0 49e0cd22f6bd9510fe65084e023d9c4316b446a6

    解释:打标签不必要在HEAD之上,也可在之前的版本上打,这需要你知道某个提交对象的校验和,通过git log命令获取。

发布标签

  • 将v0.1.0标签提交到git服务器

    $ git push origin v0.1.0

    解释:通常的git push不会将标签对象提交到git服务器,我们需要进行显式的操作。

  • 将本地所有标签一次性提交到git服务器

    $ git push origin –tags

一般用法

  • git tag -m “修改内容或版本说明” tag名

  • 将所有标签提交远程 git push origin –tags

剑指Java面试-Offer直通车

视频地址 https://www.bilibili.com/video/av55388110/?p=3

2-1 网络基础知识讲解

tcp udp 在传输层 http 应用层

2-2 TCP的三次握手_1

传输控制协议TCP简介

  • 面向连接的、可靠的、基于字节流的传输层通信协议
  • 将应用层的数据流分割成报文段并发送给目标节点的TCP层
  • 数据包都有序号,对方收到则发送ACK确认,未收到则重传
  • 使用校验和来检验数据在传输过程中是否有误

ACK: 确认序号标志

SYN: 同步序号,用于建立连接过程

FIN: finish标志,用于释放连接

握手是为了建立连接,TCP三次握手的流程图如下:

使用java8将list转为map

常用方式

代码如下:

1
2
3
public Map<Long, String> getIdNameMap(List<Account> accounts) {
return accounts.stream().collect(Collectors.toMap(Account::getId, Account::getUsername));
}

收集成实体本身map

代码如下:

1
2
3
public Map<Long, Account> getIdAccountMap(List<Account> accounts) {
return accounts.stream().collect(Collectors.toMap(Account::getId, account -> account));
}

account -> account是一个返回本身的lambda表达式,其实还可以使用Function接口中的一个默认方法代替,使整个方法更简洁优雅:

1
2
3
public Map<Long, Account> getIdAccountMap(List<Account> accounts) {
return accounts.stream().collect(Collectors.toMap(Account::getId, Function.identity()));
}

重复key的情况

代码如下:

1
2
3
public Map<String, Account> getNameAccountMap(List<Account> accounts) {
return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity()));
}

这个方法可能报错(java.lang.IllegalStateException: Duplicate key),因为name是有可能重复的。toMap有个重载方法,可以传入一个合并的函数来解决key冲突问题:

1
2
3
public Map<String, Account> getNameAccountMap(List<Account> accounts) {
return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity(), (key1, key2) -> key2));
}

这里只是简单的使用后者覆盖前者来解决key重复问题。

指定具体收集的map

toMap还有另一个重载方法,可以指定一个Map的具体实现,来收集数据:

1
2
3
public Map<String, Account> getNameAccountMap(List<Account> accounts) {
return accounts.stream().collect(Collectors.toMap(Account::getUsername, Function.identity(), (key1, key2) -> key2, LinkedHashMap::new));
}
  • Copyrights © 2015-2023 高行行
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信