• 2020-02-13

    龟兔赛跑问题和Floyd环检测算法

    Views: 9265 | No Comments

    例如要检测如下的环, 找出 a 点到 b 点的距离 mu, 以及环的周长 lam.

                    +----------------+
                    |                | 
    +---------------+----------------+
    a    mu         b                c
                    |       v        |
    

    用快慢指针同时遍历. 首先可知, 如果环存在, 快慢指针会在 c 点相遇. c 到 b 点的距离是 v. 那么可知, 相遇时, 快慢指针走过的距离是:

    慢: mu + m * lam + v
    快: mu + n * lam + v
    

    它们是两倍关系, 所以:

    2 * (mu + m * lam + v) = mu + n * lam + v
    2 * mu + 2 * v + 2 * m * lam = mu + n * lam + v
    v = n*lam - 2*m*lam - mu
    

    这时, 两个指针再以同样的速度前进. s 从 a 点出发, f 从 c 点出发. 可以知道, 当 s 走了 mu 距离后, 到达 b 点. 而 f 走了 mu 距离后, 也到达 b 点. 两者相遇.

    n*lam - 2*m*lam - mu + mu = n*lam - 2*m*lam
    
    Posted by ideawu at 2020-02-13 18:12:10
  • 2020-02-12

    动态规划算法的发现

    Views: 9035 | No Comments

    1. 问题可分而治之且 BFS

    首先, 问题必须是可分而治之的, 并在最后合并. 分而治之(递归)是为了穷举, 合并是为了找最优.

    Result r(costs[], target){
    	args = [];
    	for(cost in costs){
    		tmp = r(costs - cost, target - cost) + cost;
    		args += tmp;
    	}
    	return G(args);
    }
    

    虽然上面的代码是 DFS, 但形式上是 BFS, 而且也应该写成 BFS, 只不过 BFS 的代码不简洁而已.

    思考: 与贪婪算法的区别.

    2. 合并函数 G(...) 可迭代处理

    因为 G() 是可以转换成迭代的, 所以代码变成:

    Result r(costs[], target){
    	ret = PRE;
    	for(cost in costs){
    		tmp = r(costs - cost, target - cost) + cost;
    		ret = G(ret, tmp);
    	}
    	return ret;
    }
    

    PRE(开始之前)是引入的边界外的参数, 以便让代码处理逻辑简化, 不然要加 if 条件判断, 就无法在形式化上统一.

    3. 增加缓存

    Result r(costs[], target, dp){
    	cache_key = make_cache_key(costs, target);
    	if(dp[cache_key]){
    		return dp[cache_key];
    	}
    	ret = PRE;
    	for(cost : costs){
    		tmp = r(costs - cost, target - cost, dp) + cost;
    		ret = G(ret, tmp);
    	}
    	dp[cache_key] = ret;
    	return ret;
    }
    

    4. 将递归转成迭代

    #### 推导型

    Result forward(costs, target){
    	init(dp);
    	cc[PRE] = costs;
    	for(curr in range(PRE, target)){
    		costs = cc[curr];
    		for(cost : costs){
    			dp[next] = G(dp[next], dp[curr] + cost);
    			cc[next] = costs - cost if dp[next] updated;
    		}
    	}
    	return dp[target];
    }
    

    #### 回溯型

    Result backtrack(costs[], target){
    	dp[PRE] = PRE;
    	cc[PRE] = costs;
    	for(curr in range(atomic, target)){
    		for(prev in get_prev_list(curr)){
    			costs = cc[prev];
    			cost = costs.link(prev, curr); 
    			dp[curr] = G(dp[curr], dp[prev] + cost);
    			cc[curr] = costs - cost if dp[curr] updated;
    		}
    	}
    	return dp[target];
    }
    

    5. 缓存可淘汰: 滑动窗口

    这一条件不是必须的, 因为很多动态规划解法无法淘汰缓存. 如果缓存可淘汰, 而且是可以用滑动窗口的方式淘汰, 那么就是非常**经典且巧妙的**动态规划解法.

    对于推导型动态规划, 只需要缓存最长的推导距离. 对于回溯型动态规划, 只需要缓存最长的回溯距离.

    这里举的例子是单节点推导, 下一节点只依赖单一的前序节点, 但有些问题需要依赖多个前序节点才能出方案, 例如斐波那契数列. 需要注意.

    Posted by ideawu at 2020-02-12 15:57:31
  • 2020-01-15

    分而治之算法(divide and conquer)

    Views: 8680 | No Comments

    分而治之算法(divide and conquer)是计算机算法领域最常用最有效的算法之一, 体现到编程上就是树(数据结构), 递归函数. 一般的代码模板是这样的:

    func recursive(N){
    	if(!N){return;}
    	a, b = split(N); // divide 
    	proc(a);         // conquer a
    	recursive(b);      // process b
    }
    

    对于寻路, 分段处理最终达成目标这种模式的问题, 一般的代码模板是:

    func recursive(N){
    	if(!N){return;}
    	a, b = split(N); // divide 
    	r = proc(a);     // conquer a
    	if(r){recursive(r + b);}  // conquer remain + b
    	recursive(b);      // process b
    }
    

    多了一步:

    if(r){recursive(r + b);}
    

    因为前一段的剩余, 要和后一段组成新的问题, 然后被处理.

    Posted by ideawu at 2020-01-15 16:36:14 Tags:
  • 2019-04-03

    苹果 MacBook Pro 屏幕缺陷导致蓝色显示异常条纹

    Views: 33483 | 4 Comments

    最近我的 MacBook Pro 因为屏幕涂层脱落, 让苹果 Genius Bar 免费更新之后, 我发现更换后的屏幕显示效果很差, 像素颗粒非常明显, 没有苹果引以为傲的 Retina 屏幕的那种细腻效果. 我甚至一度怀疑给我更换的是一个 10 年前技术的 PC 显像管显示器. 这个问题还好, 只要不抠像素, 眼睛离屏幕稍微远一点, 就察觉不到像素了.

    前几天, 在做 Keynote 和表格的时候, 我突然发现 MacBook Pro 的显示器竟然在显示蓝色的时候出现细微的灰色条纹. 这个问题是怎么发现的呢?

    在 Keynote 里添加一个默认颜色(蓝色)的方框, 然后靠近仔细观察, 你就会发现蓝色的纯色在一条一条的灰色条纹, 像是像素之间的间隙透光. 这个蓝色不是纯蓝(#0000ff), 而是带有绿色和黄色的蓝色(大概是 #3388ff).

    blue

    之后, 对比了多台同型号同年份且没有更新过涂层脱落屏幕的 MacBook Pro, 最终确认新的苹果给换的屏幕确实不够细腻, 可以认定是低品质的.

    特别是在看 Firefox 浏览器的 LOGO 图标时, 你会发现火狐抱着的中间那个蓝色的地球, 条纹最明显!

    firefox

    我外行地分析了一下, 苹果屏幕用的 LED 屏, 每个像素由三个分别是红(R)绿(G)蓝(B)颜色的灯管组成, 通过三个颜色的灯管的不同亮度叠加, 产生不同的颜色. 如果三个灯管全部最亮, 就是白色了. 这个原理就是 Additive Color .

    RGB_illumination

    可能的原因

    有了上面的基本原理之后, MacBook Pro 低档屏幕显示蓝色出现白色条纹的原因就可以分析出来了.

    1. 生产工艺太差, LED 灯管排列间距太大.

    这个原因是很有可能. 苹果用的屏幕的品牌和型号等, 不像 PC 那么透明, 无法直观的对比不同型号的品质差异. 如果真是这个原因, 那么便是生产工艺缺陷, 导致两行像素之间的间隔太大.

    不过, 为什么蓝色(#3388ff)那么明显的. 应该涉及到单个像素的 RGB 三个灯管的排列方式.

    2. RGB 分组排列导致 R 和 G 出现在同一行

    我觉得屏幕生产厂商不太可能这么蠢, 除非有特殊考虑. 如果真的出现这种状况, 不同组的红灯和绿灯刚好组成了一条黄线, 那么出问题的蓝色(#3388ff)中的 R(33) G(88) 组成一条绿线, 同时受蓝色灯管影响, 就会变成浅白色的条纹了.

    外行分析, 如果有专业人数, 欢迎提供信息.

    Posted by ideawu at 2019-04-03 20:54:58
  • 2018-05-10

    快速排序算法(QuickSort)的代码实现

    Views: 25601 | No Comments

    快速排序算法,也即快排,是递归和分而治之这两种计算机基本思想的应用,再加上其实现逻辑复杂度较好,性能较快,所以快速排序算法非常经典。

    快速排序算法经常作为面试算法题。快速排序算法本身并不复杂,其本身的逻辑非常简单,要掌握其思想不是难事,甚至基于其实现代码的形而上学的表面形状背下来也很轻松。但是,如果仅掌握了快速排序的思想以及代码表面形状,就认为自己懂了快速排序,就是没有真正地理解。

    快速排序算法作为面试题,一是考查理论结合实践的能力,要求面试者除了知道快速排序算法的实现逻辑和代码形状,还要知道快速排序为什么快,怎么快。二是考查编码细节的能力,考虑的是人经验之外的智商和思维水平。

    Continue reading »

    Posted by ideawu at 2018-05-10 19:46:06
  • 2017-06-15

    音频编码的一些笔记

    Views: 34894 | No Comments

    名词解释

    采样率/Sampling Rate/Sampling Frequency: 表示原始音频,每秒需要多少个值来表示(1秒时间内采样多少次)。
    采样位数/Sampling Bit Depth/bits per sample(bps): 用多少比特来存储一个采样值。
    采样比特率/Sampling Bit Rate: 指原始音频每秒需要多少比特来表示,显然等于 Rate x Bits。
    帧长/Frame Duration/Frame Lenght: 表示每帧(数据块)所表示原始音频播放需要的时长。
    帧大小/Frame Size: 表示每帧(数据块)所表示原始音频播放需要的存储空间。
    比特率/Bit Rate: 对于固定长度编码,表示编码后,每秒需要多少个比特来表示。

    bits per sample 和 bits per second 的缩写是相同的容易混淆。

    G.711 Codec

    G711A - G.711 a-law, alaw, 世界用。
    G711U - G.711 μ-law, ulaw, 北美用。

    Sampling Rate: 8KHz
    Sampling Bits: 8 bit

    Bit Rate: 64 kbit/s
    FrameDuration: 10 ms
    Frame Size: 640 bit, 80 Bytes
    RTP FrameDuration: 20 ms
    每 RTP 报文含 2 个 G.711 帧。

    iLBC - internet Low Bitrate Codec

    Sampling Rate: 8KHz
    Sampling Bits: 16 bit

    Bit Rate: 13.33 kbit/s
    Frame Duration: 30 ms
    Frame Size: 400 bit, 50 Bytes

    Bit Rate: 15.20 kbit/s
    FrameDuration: 20 ms
    Frame Size: 304 bit, 38 Bytes

    参考:CISCO - Voice Over IP - Per Call Bandwidth Consumption http://www.cisco.com/c/en/us/support/docs/voice/voice-quality/7934-bwidth-consume.html

    Posted by ideawu at 2017-06-15 14:59:43 Tags: , ,
|<<<123456789>>>| 3/13 Pages, 76 Results.