Vincent He's waking life

在发现我没有道德后
对方放弃了道德绑架


  • Home

  • Visited cities

  • Cheat sheet

白话版大O算法复杂度

Posted on 2018-08-03 | In 前端 , js

大O算法

via 如何理解算法时间复杂度的表示法 O(n²)、O(n)、O(1)、O(nlogn)等? - 司马懿的回答 - 知乎 侵删

$O(1)$

先从 $O(1)$来说,理论上哈希表就是 O(1)。因为哈希表是通过哈希函数来映射的,所以拿到一个关键字,用哈希函数转换一下,就可以直接从表中取出对应的值。和现存数据有多少毫无关系,故而每次执行该操作只需要恒定的时间(当然,实际操作中存在冲突和冲突解决的机制,不能保证每次取值的时间是完全一样的)。举个现实的例子,比如我的身后有一排柜子,里面有香蕉(代号 B),苹果(代号 A),葡萄(G),现在你说 A,我迅速的就把苹果递过来了;你说 B,我迅速就把香蕉递过来了。就算你再增加菠萝(P)、火龙果(H),但是你说一个代号,我递给你相应的水果这个速度是几乎不会变的。


$O(n)$

至于 $O(n)$ ,这个就是说随着样本数量的增加,复杂度也随之线性增加。典型的比如数数。如果一个人从 1 数到 100,需要 100 秒,那么从 1 到 200,基本上不会小于 200 秒,所以数数就是一个 $O(n)$ 复杂度的事情。一般来说,需要序贯处理的算法的复杂度,都不会低于 $O(n)$ 。比如说,如果我们要设计一个算法从一堆杂乱的考试的卷子里面找出最高的分数,这就需要我们从头到尾看完每一份试卷,显然试卷越多,需要的时间也越多,这就是一个 $O(n)$ 复杂度的算法。


$O(n^2)$

而$O(n^2)$ 是说,计算的复杂度随着样本个数的平方数增长。这个例子在算法里面,就是那一群比较挫的排序,比如冒泡、选择等等。沿着我们刚才的说的那个试卷的例子,等我们找出最高的分数之后,放在一边另起一堆,然后用同样的方法找第二高的分数,再放到新堆上…… 这样我们做 n 次,试卷就按照分数从低到高都排好了。因为有 n 份试卷,所以这种翻试卷,找最高分的行为,我们要做 n 次,每次的复杂度是 $O(n)$ ,那么 n 个 $O(n)$ 自然就是 $O(n^2)$

在比如说构建一个网络,每个点都和其他的点相连。显然,每当我们增加一个点,其实就需要构建这个点和所有现存的点的连线,而现存的点的个数是 n,所以每增加 1,就需要增加 n 个连接,那么如果我们增加 n 个点呢,那这个连接的个数自然也就是 $n^2$ 量级了。

无论是翻试卷,还是创建网络,每增加一份试卷,每增加一个点,都需要给算法执行人带来 n 量级的工作量,这种算法的复杂度就是 $O(n^2)$。


O(nlogn)

然后是 $O(nlogn)$ ,这恐怕是常见算法复杂度里面相对最难理解的,就是这个 log 怎么来的。前面那个 n,代表执行了 n 次 $log(n)$ 的操作,所以理解了$log(n)$,就理解了$nlog(n)$。

$O(logn)$的算法复杂度,典型的比如二分查找。设想一堆试卷,已经从高到底按照分数排列了,我们现在想找到有没有 59 分的试卷。怎么办呢?先翻到中间,把试卷堆由中间分成上下两堆,看中间这份是大于还是小于 59,如果大于,就留下上面那堆,别的丢掉,如果小于,就留下下面那堆,丢掉上面。然后按照同样的方法,每次丢一半的试卷,直到丢无可丢为止。

假如有 32 份试卷,你丢一次,还剩 16 份 ,丢两次,还剩下 8 份,丢三次,就只剩下 4 份了,可以这么一直丢下去,丢到第五次,就只剩下一份了。而 $log_2(32) = 5$ 。也就是我们一次丢一半,总要丢到只有一份的时候才能出结果,如果有 n 份,那么显然我们就有:

$$\frac{n}{2^k} = 1\Rightarrow k = log_2 n$$

也就是大约需要$log_2 n$次,才能得出“找到”或者“没找到”的结果。当然你说你三分查找,每次丢三分之二可不可以?当然也可以,但是算法复杂度在这里是忽略常数的,所以不管以 2 为底,还是以什么数为底,都统一的写成 $log(n)$的形式。

理解了这一点,就可以理解快速排序为什么是 $O(nlogn)$ 了。比如对一堆带有序号的书进行排序,怎么快呢?就是随便先选一本,然后把号码大于这本书的扔右边,小于这本书的扔左边。因为每本书都要比较一次,所以这么搞一次的复杂度是 $O(n)$,那么快排需要我们搞多少次呢?这个又回到了二分查找的逻辑了,每次都把书堆一分为二,请问分多少次手里才能只剩下一本书呢?答案还是 $logn$ 。而从代码的角度来说,在到达大小为一的数列之前,我们也是需要作 $logn$ 次嵌套的调用。

CROS 跨域排坑记

Posted on 2016-12-11 | In 前端 , js

简单请求和非简单请求

浏览器将 CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

  • 请求方法是以下三种方法之一:
    • HEAD
    • GET
    • POST
  • HTTP 的头信息不超出以下几种字段:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

凡是不同时满足上面两个条件,就属于非简单请求。

浏览器对于非简单请求的处理

  • 自动发出一个”预检”请求,使用OPTIONS方法
  • 3 个关键头字段
    • Origin 表示请求来自哪个源
    • Access-Control-Request-Method *必需,列出浏览器的 CORS 请求会用到哪些 HTTP 方法
    • Access-Control-Request-Headers *非必需,列出浏览器 CORS 请求会额外发送的头信息字段

本地开发环境如何跨域联调

方法 1,chrome 插件

Allow-Control-Allow-Origin: *

此方法简单粗暴,但是缺点明显:如果服务端已指定 Access-Control-Request-Method,则此方法无效

方法 2,Charles /fiddler

以 Charles 为例:

menu

menu

menu

如果服务端已指定 Access-Control-Request-Method,可以修改之:

menu

Live App 页面布局

Posted on 2015-05-28 | In 前端 , css

一些知识

屏幕宽高比

  • 主流安卓 720p 手机 720/1280=0.5625
  • 主流安卓 1080p 手机 1080/1920=0.5625
  • 主流安卓 1440p 手机 1440/2560=0.5625
  • iPhone5 640/1136≈0.56
  • iPhone6 750/1334≈0.56
  • iPhone6P 1242/2208≈0.56 (实际运行分辨 1080p)

查看更多

iPhone 的状态栏(信号电量栏)高度:40px

iPhone 微信的返回栏高度 88px

  • 微信浏览器可视高度 - iphone5 1136-40-88=1008px - iphone4 960-40-88=832px

关于 dppx

dpr(Device Pixel Ratio 设备像素比)

上面所说的 px 是设备像素(Device Pixels),对于我们在 web 开发中接触到的是 css 像素(CSS Pixel),retina 屏幕出现以后,设备像素和 css 像素不再是 1:1 的关系.各厂家和平台通常会通过一个比值 dpr 将分辨率转换为一个较为便于开发的像素.打个比方说,iPhone5 的设备像素是 640x1136,它的 dpr 是 2,所以在 web 页面的 css 计算中需要将 640x1136 除以 2,按 320x568 计算

dppx: Number of dots per px unit. (每像素包含点的数量)

dppx 在数值上等于 dpr

查看更多设备的 dppx

dpi

题外话,dpi 是设备分辨率(Device Pixels)和设备物理尺寸(单位:英寸)之间的比值,跟我们 web 前端开发没有一毛钱关系,我们不要理它.


此分隔线以下所有内容均指 css 像素,不再讨论设备像素

极端宽高比

  • iPhone4 在微信浏览器中 320x416
  • iphone5 在 safari 桌面快捷方式中(无地址栏) 320x548


一些案例

有道云笔记 乱入学霸の世界

链接

  • 布局方式:流式布局
  • 向下兼容:主体部分高度不变

416
528

1
2
3
4
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
1
2
3
4
5
6
7
8
if (client_height < 540 && client_height > 500) {
$("body").addClass("hehe_screen");
}
if (client_height < 420) {
$("body").addClass("very_low_screen");
} else if (client_height < 500) {
$("body").addClass("low_screen");
}
1
2
3
.very_low_screen .q_0_container {
margin-top: -150px;
}

淘宝网|万能时装屋

链接

  • 纯图片素材,无文字,无表单
  • 布局方式:采用百分比绝对定位
  • 向下兼容:尽量保持主要区域可见.可以看见对于高度极端不足的 iphone4 屏幕实际上是舍弃了(东西点不到)
  • 整个页面未写 height 属性,所有background-image容器均使用padding-bottom撑出高度

416
528

1
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0" />
1
2
3
4
5
6
7
html,
body {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
}
1
2
3
4
5
6
7
8
.sprue {
position: absolute;
left: 18.06%;
top: 0.2%;
width: 82.28%;
padding-bottom: 156.25%;
background-size: cover;
}

(淘宝)男人爱车 没玩没了

链接

  • 纯图片
  • 固定宽度 640
  • 定位:按像素绝对定位
  • 向下兼容:主要内容都在画面上半部分,下面的截掉了就截掉了无所谓
1
2
3
4
<meta
name="viewport"
content="width=640, user-scalable=no, target-densitydpi=device-dpi"
/>

416
528

(京东)京东 618 全民红包摇摇摇

链接

  • 图片+文字
  • rem
  • 向下兼容: 超出部分有内容则出滚动条,除此之外也是放任截掉
1
2
3
4
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>

416
528

416
528

京东微信购物礼包

链接

  • 高度不固定
  • 流式布局
  • rem

计算<html>标签 font-size 的算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
!(function() {
var cw = document.documentElement.clientWidth || document.body.clientWidth,
zoom = cw / 320;
if (cw > 640) zoom = 2;
document.write(
'<style id="htmlzoom">html{font-size:' + zoom * 50 + "px;}</style>"
);
window.addEventListener("resize", function() {
(cw = document.documentElement.clientWidth || document.body.clientWidth),
(zoom = cw / 320);
if (cw > 640) zoom = 2;
document.getElementById("htmlzoom").innerHTML =
"html{font-size:" + zoom * 50 + "px;}";
});
})();

京东微信购物 1 周年

链接

  • 绝对定位(像素)
  • 向下兼容:缩放
1
2
3
4
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
/>
1
2
3
element.style {
zoom: 0.693333333333333;
}

416
528

总结

  1. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> 强制页面全宽
  2. (设计)主要内容尽量放在页面靠上部分,至少兼容 iPhone4s
  3. 流式布局用 rem 体验最佳
  4. 全图片页面可以考虑所有元素绝对定位

两分钟重装 sublime text 2

Posted on 2014-10-27 | In power user of everything , 前端 , tool chain

sublime text 虽好,却无奈会时不时会崩溃掉(频率 < 2 次/年),而又只能手动安装、配置插件.故将符合本人使用习惯的版本还原方法在此备份如下:

1.

打开 Sublime Text 2,按下** Control + `** 调出 Console,通常这个快捷键会与 PC 上的其它软件起冲突,需要修改其它软件的这个快捷键。

2.

将以下代码粘贴进命令行中并回车:
import urllib2,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp) if not os.path.exists(ipp) else None;open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read())

3.

重启 Sublime Text 2,如果在 Preferences -> Package Settings中见到Package Control这一项,就说明安装成功了。

4.

comond+shift+p → pci → **Flatland **

5.

preference → setting-user :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"color_scheme": "Packages/Color Scheme - Default/Monokai Bright.tmTheme",
"default_line_ending": "unix",
"ensure_newline_at_eof_on_save": true,
"font_face": "courier new",
"font_size": 15.0,
"highlight_line": true,
"ignored_packages":
[
"Vintage",
"jQuery Mobile Snippets"
],
"scroll_past_end": false,
"tab_size": 4,
"theme": "Flatland Dark.sublime-theme",
"trim_trailing_white_space_on_save": true,
"word_wrap": true
}

6.

preference → key bindings-user :

1
;[{ keys: ['super+alt+l'], command: 'reindent', args: { single_line: false } }]

7.

comond+shift+p → pci :
emmet
ejs
less
juery
Prefixr
sublimeCodeIntel
Bracket Highlighter
markdown preview

8.

拷贝备份的.sublime-snippet 到 :
/Users/userName/Library/Application Support/Sublime Text 2/Packages/User

apache配置备忘

Posted on 2014-09-28 | In 前端 , tool chain

举个栗子:

1
2
3
4
5
6
<Directory "/Users/HeXing/Sites">
Options Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>

Options Indexes FollowSymLinks

配置目录/Users/HeXing/Sites,如果你的文件根目录里有 index.html,浏览器就会显示 index.html 的内容,如果没有 index.html,浏览器就会显示文件根目录的目录列表,目录列表包括文件根目录下的文件和子目录。要禁止 Apache 显示目录结构列表,只需将 Option 中的 Indexes 去掉即可。

AllowOverride

在 AllowOverride 设置为 None 时, .htaccess 文件将被完全忽略。当此指令设置为 All 时,所有具有 “.htaccess” 作用域的指令都允许出现在 .htaccess 文件中。从安全性考虑,根目录的 AllowOverride 属性一般都配置成不允许任何 Override,即AllowOverride None.

AllowOverride 的参数:

AuthConfig 允许使用与认证授权相关的指令(AuthDBMGroupFile, AuthDBMUserFile, AuthGroupFile, AuthName, AuthType, AuthUserFile, Require 等)。
FileInfo 允许使用控制文档类型的指令(DefaultType, ErrorDocument, ForceType, LanguagePriority, SetHandler, SetInputFilter, SetOutputFilter, mod_mime 中的 Add 和 Remove 指令等等)、控制文档元数据的指令(Header, RequestHeader, SetEnvIf, SetEnvIfNoCase, BrowserMatch, CookieExpires, CookieDomain, CookieStyle, CookieTracking, CookieName)、mod_rewrite 中的指令(RewriteEngine, RewriteOptions, RewriteBase, RewriteCond, RewriteRule)和 mod_actions 中的 Action 指令。

Indexes 允许使用控制目录索引的指令(AddDescription, AddIcon, AddIconByEncoding, AddIconByType, DefaultIcon, DirectoryIndex, FancyIndexing, HeaderName, IndexIgnore, IndexOptions, ReadmeName, 等)。

Limit 允许使用控制主机访问的指令(Allow, Deny, Order)。Options[=Option,…] 允许使用控制指定目录功能的指令(Options 和 XBitHack)。可以在等号后面附加一个逗号分隔的(无空格的)Options 选项列表,用来控制允许 Options 指令使用哪些选项。

Order Allow Deny

via Fwolf’s Blog
Allow和Deny可以用于 apache 的 conf 文件或者.htaccess 文件中(配合 Directory, Location, Files 等),用来控制目录和文件的访问授权。

所以,最常用的是:

1
2
Order Deny,Allow
Allow from All

注意“Deny,Allow”中间只有一个逗号,也只能有一个逗号,有空格都会出错;单词的大小写不限。上面设定的含义是先设定“先检查禁止设定,没有禁止的全部允许”,而第二句没有 Deny,也就是没有禁止访问的设定,直接就是允许所有访问了。这个主要是用来确保或者覆盖上级目录的设置,开放所有内容的访问权。

按照上面的解释,下面的设定是无条件禁止访问:

1
2
Order Allow,Deny
Deny from All

如果要禁止部分内容的访问,其他的全部开放:

1
2
Order Deny,Allow
Deny from ip1 ip2

或者

1
2
3
Order Allow,Deny
Allow from all
Deny from ip1 ip2

apache 会按照 order 决定最后使用哪一条规则,比如上面的第二种方式,虽然第二句 allow 允许了访问,但由于在 order 中 allow 不是最后规则,因此还需要看有没有 deny 规则,于是到了第三句,符合 ip1 和 ip2 的访问就被禁止了。注意,order 决定的“最后”规则非常重要,下面是两个错误的例子和改正方式:

1
2
3
Order Deny,Allow
Allow from all
Deny from domain.org

错误:想禁止来自 domain.org 的访问,但是 deny 不是最后规则,apache 在处理到第二句 allow 的时候就已经匹配成功,根本就不会去看第三句。 解决方法:Order Allow,Deny,后面两句不动,即可。

1
2
3
Order Allow,Deny
Allow from ip1
Deny from all

错误:想只允许来自 ip1 的访问,但是,虽然第二句中设定了 allow 规则,由于 order 中 deny 在后,所以会以第三句 deny 为准,而第三句的范围中又明显包含了 ip1(all include ip1),所以所有的访问都被禁止了。 解决方法一:直接去掉第三句。 解决方法二:

1
2
3
Order Deny,Allow
Deny from all
Allow from ip1

搬运google fonts v10

Posted on 2014-09-24 | In 杂

刚弄好了梯子,分享给围墙里面的同学:

[百度网盘]

OS X 不能使用 127.0.0.2 的解决方法

Posted on 2014-09-17 | In power user of everything

原因

FreeBSD (also OS X, and I believe NetBSD & OpenBSD) will respond to requests sent to configuredaddresses on the loopback interface, just as they would for addresses on any other interface – If you want an answer you need to assign the address first:

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
mgraziano@monitor ~]$ ifconfig lo0
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
options=3<RXCSUM,TXCSUM>
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
nd6 options=3<PERFORMNUD,ACCEPT_RTADV>

[mgraziano@monitor ~]$ ping 127.1.1.1
PING 127.1.1.1 (127.1.1.1): 56 data bytes
ping: sendto: Can't assign requested address
^C

[mgraziano@monitor ~]$ sudo ifconfig lo0 alias 127.1.1.1 netmask 0xFFFFFFFF

[mgraziano@monitor ~]$ ifconfig lo0
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
options=3<RXCSUM,TXCSUM>
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3
inet6 ::1 prefixlen 128
inet 127.0.0.1 netmask 0xff000000
inet 127.1.1.1 netmask 0xffffffff
nd6 options=3<PERFORMNUD,ACCEPT_RTADV>

[mgraziano@monitor ~]$ ping 127.1.1.1
PING 127.1.1.1 (127.1.1.1): 56 data bytes
64 bytes from 127.1.1.1: icmp_seq=0 ttl=64 time=0.020 ms
^C

解决

1
$ sudo ifconfig lo0 alias 127.0.0.2 netmask 0xFFFFFFFF

via serverfault.com

关于 css position:fixed 和 transform 的一点研究

Posted on 2014-09-02 | In 前端 , css

先摘抄 w3school 对position:fixed和transform:translate()的定义:

position:fixed
生成绝对定位的元素,相对于浏览器窗口进行定位。
元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。

transform
transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜。

理论上来说 style 为position:fixed的元素,不管他的父、子、兄弟元素如何变化,他的位置相对于屏幕可视区域的位置都是不会变化的.但是在实际操作中却发现并非如此,如下是一个简单的 demo:

DEMO:

查看源码 on [runjs.cn](http://runjs.cn/code/acnggx22)

Dom 结构如下:

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<body>
<div id="wrap">
<div id="fixed">
</div>
</div>
</body>
</html>

样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#wrap {
width: 300px;
height: 300px;
}
#wrap.transformed {
transform: rotate(15deg) translate(12px, 20px);
}
#fixed {
position: fixed;
width: 100px;
height: 100px;
bottom: 0;
right: 0;
}

两个按钮:

作用分别是给#wrap添加和去除transform属性.

1
2
3
4
5
6
7
$('#addtBtn').on('click', function() {
$('#wrap').addClass('transformed')
})

$('#removeBtn').on('click', function() {
$('#wrap').removeClass('transformed')
})

很容易发现,当设置为position: fixed的元素的父元素有transform属性时,子元素不再**”相对于浏览器窗口进行定位”**,而是变为相对于有transform属性的父元素定位,以 w3c 给出的定义来看,这应该是一个 bug.


小结:

transform作为 css3 的主要属性,他的值其实更像是一个个方法.打个比方来说,如果说 css2 的属性都是”静态”的属性,浏览器在渲染页面的时候,css 渲染引擎是先将这些静态的样式渲染出来,再来计算 css3 的那些”方法”.也就是说,transform属性是后产生作用.反映出的现象就是transform优先更高,甚至高于position: fixed.

以上是我的一点粗陋的推想,请斧正,谢谢.

coding.net 是个好东东

Posted on 2014-08-30 | In power user of everything

前几天发现有个垃圾站的域名是 xxx.coding.net,当时还闪了一下怎么垃圾站的域名都这么高大上了.也没多长个心眼去看看顶级域名是什么情况.

直到昨天上班遇到一个需求,把一个 php 做的 demo 放到外网,我去找免费 php 空间的时候又一次搜到了这个神奇的网站.

经过我近一天的使用,感觉coding.net是想做成中国的 github,同样可以建立远程 git 库,可以 clone 别人的 git 库,可以 fork…等等等等.但是这货比 github 强在它的演示空间居然提供 php 环境(github.io 只提供静态空间)!只需要简单的把本地的工程 push 到云端,配置好数据库,再切换到演示面板,点击部署就不用管了..实测访问速度超过某些号称高速的 vps(服务器在国内就是好).

coding.net演示界面截图

coding.net不支持 github.io 的自动部署,每次 push 代码之后需要手动点一下一键部署.

目前coding.net还不支持绑定域名,只能用它提供的二级域名.估计以后也不会提供绑定域名吧,那样的话建站蝗虫大军就该找它了.


顺便放上最近做的一个项目的前端 demo

fork me on [coding.net](https://coding.net/stariveer/O2O_demo.git).

Over

给新博客弄了个 404 页面

Posted on 2014-08-26 | In power user of everything

很简单,在/source/下新建 404.html,里面内容自由发挥.
如果不想让 hexo 自作主张的渲染,可以在文件开始处加上

1
## layout: false

Over.
可以在这里看到效果哦

<i class="fa fa-angle-left" aria-label="Previous page"></i>1…345<i class="fa fa-angle-right" aria-label="Next page"></i>

41 posts
10 categories
46 tags
GitHub E-Mail Twitter Douban Zhihu
© 2014 — 2025 Vincent He