摘要:
又一次看到讨论“洗牌”算法的文章,奇怪不少人喜欢造轮子,但造的轮子却远没有STL的random_shuffle好用。 “洗牌”算法: 若某个序列里面的每个元素在每个位置已经等概率出现,那么新增加一个元素,只要新增加的元素和所有元素进行等概率交换,则新序列中每个元素在每个位置仍是等概率出现。 (若原来有n个元素,新增加的第n+1个元素在任一位置b的概率显然是1/(n+1),在同一位置b,原来的n个元素在该位置仍是等概率出现的,出现的概率为(1-1/(n+1))/n = 1/(n+1)。 也可以这样算:进行随机交换前,原来的某个元素在某个位置出现的概率为1/n,被交换的概率为1/(n+1),因而. 阅读全文
摘要:
《编程之美》读书笔记15: 4.5 磁带文件存放优化 对一个已经是最优解的排列,记第i个文件的长度为Bi,被访问概率为Ai。如果交换第i个和第i+1个文件,则平均长度一定不会变小,交换后,访问原第i个文件时,要多访问一个原第i+1文件,长度增加了Ai*Bi+1,而访问原第i+1个文件时,要少访问一个原第i个文件,长度减少了Ai+1*Bi,而访问这两个文件之前和之后的文件,长度没有改变,故有: Ai*Bi+1 - Ai+1*Bi >=0 即Ai/Bi >= Ai+1/Bi+1, 由于i可以任意取,因而A0/B0 >= A1/B1 >= A2/B2 >= … > 阅读全文
摘要:
《编程之美》读书笔记14: 4.4 是否在三角形内 对几何题目,常用到矢量。若P点在三角形内部,则矢量PA沿时钟某个方向三次旋转分别经过PB、PC再回到PA,每次旋转角度都不会超过180度。即PA×PB、PB×PC和PC×PA这三个矢量积应该都为正,或都为负。如果P在三角形边上,则这三个矢量积应该一个为0,其它两个同正或同负。若在三角形某个顶点,则三个矢量积,必有两个为0,一个不为0。若A B C三点共线,P在这直线上,则所有矢量积均为0,若P不在这直线上,则为两正一负或两负一正。 structPoint{doublex;doubley;};staticintdi 阅读全文
摘要:
《编程之美》读书笔记13: 4.1 金刚坐飞机问题 问题: 现在有一班飞机将要起飞,乘客们正准备按机票号码(1, 2, 3, …N)依次排队登机。突然来了一只大猩猩(对,他叫金刚)。他也有飞机票,但是他插队第一个登上了飞机,然后随意地选了一个座位坐下了1。根据社会的和谐程度,其他的乘客有两种反应: 1. 乘客们都义愤填膺,“既然金刚同志不遵守规定,为什么我要遵守?”他们也随意地找位置坐下,并且坚决不让座给其他乘客。 2. 乘客们虽然感到愤怒,但还是以“和谐”为重,如果自己的位置没有被占领,就赶紧坐下,如果自己的位置已经被别人(或者金刚同志)占了,就随机地选择另一个位置坐下,并开始闭目养神,不再 阅读全文
摘要:
《编程之美》读书笔记19: 3.9 重建二叉树 对根节点a以及先序遍历次序P和中序遍历次序I,查找a在I中的位置,将I分为两部分,左边部分的元素都在a的左子树上,右边的元素都在a的右子树上,因而可以确定a的左子树节点数和a的右子树节点数,再结合P,可以确定a的左孩子和右孩子,以及各个孩子的先序和中序遍历次序。 由于已经知道节点数,可以事先分配好内存,可以按先序遍历次序连续存放节点。 rebuild_tree_1structNode{Node*left;Node*right;chardata;};voidrebuild(charpreorder[],charinorder[],Noderesu. 阅读全文
摘要:
《编程之美》读书笔记16: 3.10 分层遍历二叉树 看到Milo写的这篇文章,又翻了下书,发现书的代码(P253)有个瑕疵,每个节点值后面都会显示一个空格,如果将间隔字符改为“-”,输出的每行最后都有一个“-”,不能达到要求。不过,只要将 cout << vec[cur] -> data << " "; 这行改为: if (cur==last-1) cout << vec[cur] -> data << "\n"; else cout << vec[cur] -> data 阅读全文
摘要:
《编程之美》读书笔记12: 3.8 求二叉树中节点的最大距离 问题: 如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数。写一个程序求一棵二叉树中相距最远的两个节点之间的距离。 实际上就是求树的直径。若采用“动态规划方法”思想,会将该问题分解成“具有最大距离两点间的路径是否经过根节点”两个子问题,然后再对这两个子问题求解判断。实际上,不必这么麻烦。距离最远的两点必然在以某个节点A为根的子树上,它们间的路径必然经过该子树的根节点A。因而,以任意一个节点B为根的子树,计算出经过该子树根节点B的最大距离,则所有最大距离的最大值就是 阅读全文
摘要:
《编程之美》读书笔记11: 3.3 计算字符串的相似度 很经典的可使用动态规划方法解决的题目,和计算两字符串的最长公共子序列相似。 设Ai为字符串A(a1a2a3 … am)的前i个字符(即为a1,a2,a3 … ai) 设Bj为字符串B(b1b2b3 … bn)的前j个字符(即为b1,b2,b3 … bj) 设 L(i , j)为使两个字符串和Ai和Bj相等的最小操作次数。 当ai等于bj时 显然L(i, j)=L(i-1, j-1) 当ai不等于bj时 若将它们修改为相等,则对两个字符串至少还要操作L(i-1, j-1)次 若删除ai或在Bj后添加ai,则对两个字符串至少还要操作L(i-. 阅读全文
摘要:
《编程之美》读书笔记18: 3.7 队列中取最大数操作问题 若不使用C++新标准的右值引用,DeQueue的实现是低效的,因为要返回的元素只能通过赋值操作,而不能通过引用。(书上的实现代码,竟然少了对EnQueue的实现!) 思路:用一个辅助队列来记录最大元素(为节省空间,只记录其地址),当有一个元素入队,就将辅助队列尾端不大于该元素的全部出队后(注意相等的也要出队),再将该元素压入辅助队列,这样就保证,辅助队列从头到尾的元素是递减的,辅助队列头元素是当前队列的最大值。当有一个元素出队时,就与辅助队列的头部第一个元素所指的元素比较,如果是同一个元素(注意不是相等),辅助队列头部就执行出队操作. 阅读全文
摘要:
《编程之美》读书笔记09: 2.17 数组循环移位 对长度为n的数组(ab)左移k位,最直接的方法,就是用stl的rotate函数(stl针对三种不同的迭代器,提供了三个版本的rotate)。但在某些情况下,用stl的rotate效率极差。 对数组循环,可以采用的方法有: ① 动态分配一个同样长度的数组,将数据复制到该数组并改变次序,再复制回原数组。 ② 利用ba=(br)r(ar)r=(arbr)r,通过三次反转字符串。 ③ 分组交换(尽可能使数组的前面连续几个数为所要结果): 若a长度大于b,将ab分成a0a1b,交换a0和b,得ba1a0,只需再交换a1 和a0。 若a长度小于b,将a. 阅读全文