主要是根据编程珠玑后面的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算法总结的更多相关文章

  1. Select 选择算法 - 编程珠玑(续) 笔记

    Select 算法 I 编程珠玑(续)介绍的 Quickselect 算法 选择 N 个元素中的第 K 小(大)值,是日常场景中常见的问题,也是经典的算法问题. 选取 N 个元素的数组的中的第 K 小 ...

  2. 读书笔记--编程珠玑II

    学化学的应该都知道chemdraw,这是一款专门绘制化学结构的软件,什么苯环.双键各种word难以搞定的分子式,你可以轻松的用chemdraw完成,可以称得上化学工作者居家旅行必备的良药.其实早在19 ...

  3. 《编程珠玑(第2版)》【PDF】下载

    <编程珠玑(第2版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382225 内容简介 书的内容围绕程序设计人员面对的一系列实 ...

  4. 《编程珠玑,字字珠玑》读书笔记完结篇——AVL树

    写在最前面的 手贱翻开了<珠玑>的最后几章,所以这一篇更多是关于13.14.15章的内容.这篇文章的主要内容是“AVL树”,即平衡树,比红黑树低一个等次.捣乱真惹不起红黑树,情况很复杂:而 ...

  5. Programming pearls 编程珠玑的题目

    Programming pearls 编程珠玑的题目 这段时间有空都在看编程珠玑,很经典的一本书,一边看一边用 python 做上面的题目,我做的都放到 github 上了 https://githu ...

  6. <转载>编程珠玑-位排序(bitsort)

    转载:http://www.cnblogs.com/shuaiwhu/archive/2011/05/29/2065039.html  维护版权   在<编程珠玑>一书上,有一题是将一堆不 ...

  7. Siki_Unity_3-13_编程内功修炼-算法

    Unity 3-13 编程内功修炼 -- 算法 任务1&2:课程介绍 主要算法: 分治法 堆排序 二叉树 动态规划 贪心算法 图 任务3:分治算法 -- Divide and Conquer ...

  8. 声明函数指针、回调函数、函数对象------c++程序设计基础、编程抽象与算法策略

    声明函数指针 #include<iostream> using namespace std; double a(double aa) { return aa; } int main() { ...

  9. 内存布局------c++程序设计基础、编程抽象与算法策略

    图中给出了在一个典型c++程序中如何组织内存的框架.程序中的指令(在底层都是按位存储的).全局变量.静态对象和只读常量往往被存储在静态去(static area)(第二个图中的数据段.代码段.值得注意 ...

随机推荐

  1. 利用CSS3选择器定制checkbox和radio

    之前在一个项目中需要定制checkbox,于是乎用图片模拟了一下,之后发现个更好用的方法(*因为兼容问题 在移动开发中用用就好) 效果: 1 2 3 4 5 6 7 实现代码: <style t ...

  2. sqlmap新手注入

    一 什么是sqlmap sqlmap is an open source penetration testing tool that automates the process of detectin ...

  3. Hibernate防止SQL注入

    如果在查询字段中输入单引号"'",则会报错,这是因为输入的单引号和其他的sql组合在一起编程了一个新的sql,实际上这就是SQL注入漏洞,后来我在前台和后台都对输入的字符进行了判断 ...

  4. C++临时对象销毁时间

    下面这段代码会输出什么? const char* p = string("hello temprary string").c_str(); cout << p; 下面这 ...

  5. iOS多线程系列(1)

    多线程这个概念的接触是蛮早的时候了,当时还是单核单CPU的时候,Thread这个概念已经出现了,当时比较流行的方案是时间片轮流,线程可以优先级抢占,但一次只能运行一个线程,实际上多线程是不能真正并行处 ...

  6. AndroidUI 侧滑菜单 DrawerLayout的使用

    直接上代码: activity_main.xml: <android.support.v4.widget.DrawerLayout xmlns:android="http://sche ...

  7. 兔子--Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK

    错误原因: Activity打开别的Activity的时候会默认把新的Activity放到自己的task中,所以不用指定,可是别的地方就得指定了. 解决的方法:intent.addFlags(Inte ...

  8. windows编程之菜单操作

    分清几个概念 <1>"主菜单" 和 "顶层菜单" 是一个意思. <2>主菜单中的项目叫做 "弹出菜单" 或者 &qu ...

  9. Java面试题之Request对象的主要方法

    setAttribute(String name,Object):设置名字为name的request的参数值 getAttribute(String name):返回由name指定的属性值 getAt ...

  10. SharePoint 2013设置“以其他用户身份登录”

    登录web服务器,打开位于“C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\CONTR ...