编程珠玑I算法总结
主要是根据编程珠玑后面的Algorithm附录总结了一下这本书里面的经典算法。
1 辗转相减求最大公约数
思想:最大公约数能整除i和j,则其一定也能整除i-j(if i>j)
int gcd(int i, int j)
{
while(i != j)
{
if(i > j) i-=j;
else j-=i;
}
return i;
}
2 快速求取x的n次方
思想:充分利用了已经计算出来的数据防止重复计算来减少了算法运行时间
function exp(x,n)
//pre n>=0 //post result = x^n
{
if n=0 return 1;
else if even(n)
return square(exp(x,n/2));
else return x*exp(x,n-1);
}
3 计算 y的多项式,
思想:迭代利用前面计算的结果计算后面
y = a[n];
for i in [n-1,0]
y = y*x + a[i];
4 从[l,u]随机取数,数的范围可到30bit。
32位机上RAND_MAX是0x7fff
int bigrand() { return RAND_MAX*rand() + rand(); }
int randint(int l, int u) { return l + bigrand()%(u-l+1); }
5 从n中随机地取m个元素,并按序输出
洗牌算法:
void genshuf(int m, int n)
{
int *x = new int[n];
for(int i=0; i < n; i++)
x[i] = i;
for(int i=0; i < m; i++)
{
j = randint(i,n-1); //洗牌的精髓
swap(x[i],x[j]);
}
sort(x,x+m);//保证按序输出
for(int i=0; i < m; i++)
cout<<x[i]<<endl;
}
来算算概率,开始整个数组以固定方式初始化。接着每个元素以rand方式和所有元素交换,这保证了随机,时间复杂度O(nlogn)
Knuth算法,来自《计算机程序设计艺术》:
//////////////////////////////////////////////////////////////////////////
//pre: 0<=m<=n , n is 0 to n-1
//post: print m numbers selected from n
void GenKnuth(int m, int n)
{
for(int i=0; i < n; i++)
{
if((rand()%(n-i)) < m)//此时选取概率为toSelected/Remaining
{
std::cout<<i<<" ";
m--;
}
}
}
时间复杂度O(n)。
集合算法:
//
Initialize set S to empty
size = 0
while size < m do
t = bigrand() % n
if t is not in S
insert t into S
size++
print the elements of S in sorted order
这个算法的缺点在于如果m和n接近的时候,比较失败(已在集合的概率)会很大从而降低性能,时间复杂度也为O(nlogn)
改进集合算法:
//
void genfloyd(int m, int n)
{
set<int> S;
set<int>::iterator i;
for(int j=n-m; j < n; j++)
{
int t = bigrand()%(j+1);
if(S.find(t) == S.end())
{
S.insert(t); // t not in S
}
else
{
S.insert(j); // t in S
}
}
输出所有数字
}
6 Problem: Rotate a one-dimensional vector of n elements left by i positions.
■常规解法:1 copy the first i elements of x to a temporary array, movint the remaining n - i elements left i places, and then copying the first i from temporary array back to the last positions in x.这个算法需要额外的内存。2 we could define a function to rotate x left one position and call it i times,这个算法很耗时。
■Juggling act,杂耍算法: move x[0] to the temporary t, then move x[i] to x[0], x[2i] to x[i], and so on (taking all indices into x modulo n),until we come back to taking an element from x[0], at which point we instead take the element from t and stop the process. 这个算法结合了常规两个算法的优点,其中最关键的在于对需要执行次数的证明,即移动多少回(回到原来起点)才能覆盖所有数组?答案是,gcd(i,n),证明请点这里:
■翻转算法,这个算法起源于这样一个思想:Rotating the vector x is really just swapping the two segments of the vector ab to be the vector ba, where a represents the first i elements of x.由这引发了如下算法, 定义reverse(i,j),指把vector中i到j的元素翻转,那么这个代码如下:
reverse(0,i-1)
reverse(i,n-1)
reverse(0,n-1)
7 Problem: 转置矩阵
在每个矩阵数据前面加一个行号列号的数据,对这些数据先按列号进行排序再按行号排,去除前置数据。
8 Problem: maxmum sum of any contiguous subvector of a vector.
四种解法见#bookmark=id.v94teif5zuqe
9 查找字典中的回文
1 对字典中每个单词中的字母按字典序排序
2 对字典中的每个单词按字典序排序
3 回文的单词最后都被排在了一起。
10 求文本中的最长重复子串
利用后缀数组进行求解
char* FindLCS(const char* str, int len)
{
//构建后缀数组
const char** suffix = new const char*[len];
int i=0;
for(; i < len; i++)
{
suffix[i] = &str[i];
}
qsort(suffix,i,sizeof(char*),pstrcmp);//对后缀数组排序
//通过查找相邻字符串,求最长重复子串
int maxlen = 0;
int maxi = -1;
for(int l=0; l < i-1; l++)
{
int temp = 0;
if((temp = comlen(suffix[l],suffix[l+1])) > maxlen)
{
maxlen = temp;
maxi = l;
}
}
char* result = new char[len];
if(maxi != -1)
{
strncpy_s(result,len,suffix[maxi],maxlen);
}
delete [] suffix;
return result;
}
其中用到如下函数:
//给qsort用的比较函数
//pre: p1,p2指向字符串,并以'\0'结尾
//post: 如果函数的第一个参数小于第二个参数,返回负值;如果等于返回零值;如果大于返回正值
int pstrcmp(const void* p1, const void* p2)
{
return strcmp( *(char* *)p1, *(char* *)p2);
}
//求出p和q的最长公共字符数
//pre: p为母串,q为查找串,p比q长,p最后以'\0'结尾
//post: 返回所求数字
int comlen(const char* p,const char* q)
{
int i=0;
while(*p && *p++ == *q++)
i++;
return i;
}
11 寻找第k小的数字
改进快速排序算法
12 堆排序的操作 siftdown siftup(比创建堆,调整堆更原子点的操作,感觉归纳的 挺好)
见书
13 查找问题
一般解法:
顺序搜索, 可用哨兵优化
二分搜索,伪代码:
l = 0; u = n-1;
loop
if(l>u)
p = -1;break;
m = l + (u-l)/2;
case
x[m]<t: l = m+1;
x[m]>t: u = m-1;
x[m] ==t: p=m; break;
用二分求第一个出现的数据(有重复数据的时候)
l = -1; u = n;
while l+1 != u
{
m = (l + u) / 2;
if(x[m] < t)
l = m;
else
u = m;
}
p = u;
if(p >= n || x[p] != t)
p = –1
14 排序问题
一般解法:
插入排序,O(n^2), 部分有序时非常快速能在O(n)时间内解决,故快速排序再分治到小规模数据时用插入排序能够提高效率。稳定的排序算法。
for i = [1,n) t = x[i]; for(j=i; j>0 && x[j-1]>t; j--) x[j] = x[j-1]; x[j] = t;
(5行代码搞定)
快速排序,平均情况O(nlogn),最坏情况(O(n^2),空间O(n)(递归堆栈)
两种代码,前者为算法导论采用,后者是前者的优化版,比前者快常数因 子。
MIT’s(11行代码):
//pre: x[l..u]
//post:x[l..u] in increasing order
void qsort(l,u)
{
if(l >= u)
return;
//partition
i = l;
for j = [l+1,u]
/*invariant: x[l+1..i]<x[l] && x[i+1..j-1]>=x[l]*/
if(x[j] < x[l])
swap(x[++i],x[j]);
swap(x[i],x[l]);
qsort(l,i-1);
qsort(i+1,u);
}
Better Version(15行代码):
void qsort(l,u)
{
if(l >=u)
return;
t = x[l]; i = l; j = u+1;
loop
do i++ while i<=u && x[i]<t
do j -- while x[j]>t
if(i>j)
break;
swap(x[i],x[j]);
swap(x[l],x[j]);
qsort(l,j-1);
qsort(j+1,u);
}
Heap Sort:时间一直是O(nlogn),是渐进最优的排序算法。
for i = [2,n)
siftup(i);
for(i=n; i>=2; i--)
swap(1,i);
siftdown(i-1);
(5行代码搞定)
Bitmap Sort
一般需满足很数的范围在一定区间以及不重复(可不满足)等限制
for i = [0,n)
bit[i] = 0
for each i in the input file
bit[i] = 1
for i = [0,n)
if bit[i] == 1
write i on the output file
转自:http://www.cnblogs.com/HappyAngel/archive/2011/03/15/1985261.html
编程珠玑I算法总结的更多相关文章
- Select 选择算法 - 编程珠玑(续) 笔记
Select 算法 I 编程珠玑(续)介绍的 Quickselect 算法 选择 N 个元素中的第 K 小(大)值,是日常场景中常见的问题,也是经典的算法问题. 选取 N 个元素的数组的中的第 K 小 ...
- 读书笔记--编程珠玑II
学化学的应该都知道chemdraw,这是一款专门绘制化学结构的软件,什么苯环.双键各种word难以搞定的分子式,你可以轻松的用chemdraw完成,可以称得上化学工作者居家旅行必备的良药.其实早在19 ...
- 《编程珠玑(第2版)》【PDF】下载
<编程珠玑(第2版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382225 内容简介 书的内容围绕程序设计人员面对的一系列实 ...
- 《编程珠玑,字字珠玑》读书笔记完结篇——AVL树
写在最前面的 手贱翻开了<珠玑>的最后几章,所以这一篇更多是关于13.14.15章的内容.这篇文章的主要内容是“AVL树”,即平衡树,比红黑树低一个等次.捣乱真惹不起红黑树,情况很复杂:而 ...
- Programming pearls 编程珠玑的题目
Programming pearls 编程珠玑的题目 这段时间有空都在看编程珠玑,很经典的一本书,一边看一边用 python 做上面的题目,我做的都放到 github 上了 https://githu ...
- <转载>编程珠玑-位排序(bitsort)
转载:http://www.cnblogs.com/shuaiwhu/archive/2011/05/29/2065039.html 维护版权 在<编程珠玑>一书上,有一题是将一堆不 ...
- Siki_Unity_3-13_编程内功修炼-算法
Unity 3-13 编程内功修炼 -- 算法 任务1&2:课程介绍 主要算法: 分治法 堆排序 二叉树 动态规划 贪心算法 图 任务3:分治算法 -- Divide and Conquer ...
- 声明函数指针、回调函数、函数对象------c++程序设计基础、编程抽象与算法策略
声明函数指针 #include<iostream> using namespace std; double a(double aa) { return aa; } int main() { ...
- 内存布局------c++程序设计基础、编程抽象与算法策略
图中给出了在一个典型c++程序中如何组织内存的框架.程序中的指令(在底层都是按位存储的).全局变量.静态对象和只读常量往往被存储在静态去(static area)(第二个图中的数据段.代码段.值得注意 ...
随机推荐
- sql update小结
以前update用的不少,但都是简单的单表操作,没有在意,最近查阅多表关联更新及更新top n,发现update还真灵活,记录如下(在mssqlserver2008r2下测试通过): 1单表操作 u ...
- Oracle EBS-SQL (WIP-13):检查任务组件未选MRP净值.sql
select WE.WIP_ENTITY_NAME 任务号, MFG_LOOKUPS_WJS. ...
- 项目与软件推荐之编辑器-QOwnNotes(刺激自己)
项目与软件推荐之编辑器-QOwnNotes 今天推荐一款软件 QOwnNotes,是一款普通文本笔记软件.以某个路径为目录,罗列出目录下所有的 md 文件或者 txt 文件. 有如下亮点: 启动速度快 ...
- CC++初学者编程教程(6) 配置WindowsXP虚拟机与VC6.0
1.我们安装需要下列文件. 2.新建一个虚拟机. 3. 选择默认的 Vmware Work Station10.0 4. 我们选择这个WindowsXP镜像. 5. 我们复制一个WindowsXPSP ...
- Hessian Servlet和Hessian Spring的简单应用
转自: http://lancui.iteye.com/blog/935578 简介 相比WebService,Hessian更简单.快捷.采用的是二进制RPC协议(Binary),因为采用的是二进制 ...
- pagespeed 安装(chrome版和firefox版)
原文地址:http://blog.sina.com.cn/s/blog_6c9da636010103va.html pagespeed 让你的网站页面打开速度飞起来! 1.firefox版本下的安装 ...
- Struts2 一、 视图转发跳转
<struts> <constant name="struts.118n.encoding" value="UTF-8"></co ...
- CSU - 1356 Catch(dfs染色两种写法,和hdu4751比较)
Description A thief is running away! We can consider the city to N–. The tricky thief starts his esc ...
- Wormholes(SPFA+Bellman)
Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 36860 Accepted: 13505 Descr ...
- Body joints angle using Kinect
http://stackoverflow.com/questions/12608734/body-joints-angle-using-kinect-checking-time-interval?rq ...