编程珠玑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)(第二个图中的数据段.代码段.值得注意 ...
随机推荐
- 关于Nexus 7的Usb host开发问题
按照API Guides和搜索到的各种方法,都没办法把Nexus 7上面的USB 设备列举出来.使用市场上的软件依然不行. 在找demo的时候找到一位大神chainfire,他似乎有所解释 看来得换一 ...
- Linux07--Shell程序设计03 通配符与正则表达式
通配符 通配符可用于代替字符. 通常地,星号“*”匹配0个或以上的字符,问号“?”匹配1个字符. 使用情况: 1.文件和目录 在CP/M.DOS.Microsoft Windows和类Unix操作系统 ...
- 关于css中使用ul li的一些体会
参考网址:http://hi.baidu.com/july_leo/item/5237cd612070ae2668105b40 如何修改ul li的显示 ----------------------- ...
- Linux下利用fork()创建子进程并使父进程等待子进程结束
int status; pid_t t = fork(); if(t){ waitpid(t, &status, 0); }else{ system("vi temp ...
- 用gdb调试程序笔记: 以段错误(Segmental fault)为例
用gdb调试程序笔记: 以段错误(Segmental fault)为例[转] 1.背景介绍2.程序中常见的bug分类3.程序调试器(如gdb)有什么用4.段错误(Segmental fault)介绍5 ...
- C# 图片压缩 开源库
http://www.rasteredge.com/how-to/csharp-imaging/image-compressing/ http://www.rasteredge.com/dotnet- ...
- Java DES 加密和解密源码(转)
原文地址:http://www.oschina.net/code/snippet_727646_18383 Java密码学结构设计遵循两个原则: 1) 算法的独立性和可靠性. 2) 实现的独立性和相互 ...
- ACM学习-POJ-1004-Financial Management
菜鸟学习ACM,纪录自己成长过程中的点滴. 学习的路上,与君共勉. ACM学习-POJ-1003-Financial Management Financial Management Time Limi ...
- JQuery(下)
26.jQuery 中的 DOM 操作 )DOM(Document Object Model—文档对象模型):一种与浏览器, 平台, 语言无关的接口, 使用该接口可以轻松地访问页面中所有的标准组件 ) ...
- 自己写一个strcmp函数(C++)
题目说明: 写一个函数,实现两个字符串的比较.即自己写一个strcmp函数,函数原型为int strcmp( char * p1, char * p2); 设p1指向字符串s1,p2指向字符串s2.要 ...