随笔分类 -  Algorithm

摘要:首先我们来一道最简单的题目作为引子 1、已知有一个随机函数rand_0_and_1_with_p(),它能以概率p产生0,以概率1 - p产生1,只使用该函数,设计一新的随机函数,要求以等概率产生1和0。 我们知道,运行rand_0_and_1_with_p()函数一次,那么P(0) = p... 阅读全文
posted @ 2012-11-08 15:54 Mr.Rico 阅读(579) 评论(0) 推荐(0) 编辑
摘要:归并排序算法(mergesort)是将一个序列划分为同样大小的两个子序列,然后对两个子序列分别进行排序,最后进行合并操作,将两个子序列合成有序的序列.在合成的过程中,一般的实现都需要开辟一块与原序列大小相同的空间,以进行合并操作。这儿有比较全的排序算法:http://www.cnblogs.com/... 阅读全文
posted @ 2012-11-07 13:01 Mr.Rico 阅读(802) 评论(0) 推荐(0) 编辑
摘要:首先说明一下快速排序是对冒泡排序的改进。为什么这么说呢?想一下冒泡排序,它把序列分成了两部分,前半部分无序,后半部分升序排列,并且后半部分的数都大于前半部的数。由此可得到快速排序和冒泡排序的一些共同点: 都要经历n趟排序 每趟排序要经历O(n)次比较 都是后半部分元素比前半部大而不同之处就在于冒泡排序的交换操作发生相邻的元素之间,即一趟排序可以要经过多次交换操作;快速排序的交换操作发生在间隔比较远的两个元素之间,一趟排序要经过交换操作次数会少一些。一般的快速排序采用的是递归的方式进行实现的,而且一般只要是递归的问题,都可以转化为非递归的实现,而实现的时候一般采用的是堆栈数据结构。快排的主要思想 阅读全文
posted @ 2012-10-11 14:45 Mr.Rico 阅读(729) 评论(0) 推荐(0) 编辑
摘要:一个比较简单的程序题。题目虽简单,但写起来需要注意的东西还是很多的。题目:读入两个小于100的正整数A和B,计算A+B.需要注意的是:A和B的每一位数字由对应的英文单词给出.输入:测试输入包含若干测试用例,每个测试用例占一行,格式为"A + B =",相邻两字符串有一个空格间隔.当A和B同时为0时输入结束,相应的结果不要输出.输出:对每个测试用例输出1行,即A+B的值.样例输入:one + two = three four + five six = zero seven + eight nine = zero + zero =样例输出:3 90 96下面是我写的一段程序:# 阅读全文
posted @ 2012-07-16 20:46 Mr.Rico 阅读(475) 评论(0) 推荐(0) 编辑
摘要:求两个数的最大公约数问题,即常说的GCD问题,是一个经常用到的问题。这个问题的求解最常用的方法就是辗转相除的方法。这个方法其实就是下面的一个公式:gcd(a,b)=gcd(b,a%b)记住了这个公式就很容易写出它的程序了。第一:可以采用递归的方法: unsignedgcd(unsigneda,unsignedb){if(!b)returna;if(a<b)returngcd(b,a);elsereturngcd(b,a%b);}第二:所有的递归都可以转为迭代实现: unsignedgcd2(unsigneda,unsignedb){unsignedtmp;while(b!=0){tmp= 阅读全文
posted @ 2012-07-02 02:19 Mr.Rico 阅读(284) 评论(0) 推荐(0) 编辑
摘要:之前介绍过常见的排序算法,可以查看这里之前实现的代码都是针对int型的算法,现在我将代码改写成了模板,这样可以应用于常见的一些类型。为了测试比较不同的排序算法,采用了两种计时方式。注意,下面的两段代码中,void(*_sort[])(T*,int) 是函数指针数组。1. 采用clock函数,统计排序算法所使用的时钟数代码如下: template<classT>voidclock_test(){void(*_sort[])(T*,int)={insert_sort,binary_insert_sort,shell_sort,shell_sort2,select_sort,select 阅读全文
posted @ 2012-07-02 01:10 Mr.Rico 阅读(1743) 评论(0) 推荐(0) 编辑
摘要:总结一下常见的排序算法。 排序分内排序和外排序。内排序:指在排序期间数据对象全部存放在内存的排序。外排序:指在排序期间全部对象个数太多,不能同时存放在内存,必须根据排序过程的要求,不断在内、外存之间移动的排序。内排序的方法有许多种,按所用策略不同,可归纳为五类:插入排序、选择排序、交换排序、归并排序、分配排序和计数排序。插入排序主要包括直接插入排序,折半插入排序和希尔排序两种;选择排序主要包括直接选择排序和堆排序;交换排序主要包括冒泡排序和快速排序;归并排序主要包括二路归并(常用的归并排序)和自然归并。分配排序主要包括箱排序和基数排序。计数排序就一种。稳定排序:假设在待排序的文件中,存在两个. 阅读全文
posted @ 2012-07-01 16:11 Mr.Rico 阅读(11278) 评论(2) 推荐(3) 编辑
摘要:主要是利用位操作来判断每一位是否为1方法一:清除整数a最右边的1可以使用这个操作:a&(a-1)所以可以利用这个方法来得到1的个数:intcount_one(unsignedx){intcount=0;while(x){count++;x=x&(x-1);}returncount;}方法二:对整数进行移位,然后判断最后一位是否为1intcount_one2(unsignedx){intcount=0;inti=0;while(i<32){if((x>>i)&0x1)count++;i++;}returncount;}方法三:这个方法和方法二类似,只是每 阅读全文
posted @ 2012-06-21 22:57 Mr.Rico 阅读(2315) 评论(0) 推荐(0) 编辑
摘要:今天下午参加民生银行总行的笔试,最后一个题是一个小的算法题。题目:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。并且要求是用两种方法。在网上搜索了一下,网上说这是2006年google的面试题。方法1:最简单,容易想到的就是双循环的那种,从前往后进行遍历,这种的复杂度是O(n^2)简单的C++代码如下:boolmethod1(conststring&s,char&c){intlen=s.size();inti;vector<bool>flag(len);for(inti=0;i<len;i++)flag[i]=true;for( 阅读全文
posted @ 2012-06-17 23:10 Mr.Rico 阅读(1667) 评论(0) 推荐(1) 编辑
摘要:排列组合是常见的一个问题。1. 排列算法这个主要采用递归的方法来解决。具体代码如下:voidswap(int&a,int&b){if(a==b)return;intt=a;a=b;b=t;}voidperm(intarr[],intk,intm){if(k==m){copy(arr,arr+m+1,ostream_iterator<int>(cout,""));cout<<endl;}else{for(inti=k;i<=m;++i){swap(arr[i],arr[k]);perm(arr,k+1,m);swap(arr[i] 阅读全文
posted @ 2012-06-02 16:00 Mr.Rico 阅读(954) 评论(0) 推荐(1) 编辑
摘要:首先,先看看如何对数字进行循环移位C语言中没有提供循环移位的操作符,但可以通过简洁的方式实现循环移位,主要使用移位操作来实现。设一个操作数x有s位则循环左移n位的操作为: (x << n) | (x >> (s - n)); 同理右移n位位:(x >> n) | (x << (s - n));实际编程中可以用宏定义实现循环移位: #define ROTATE_LEFT(x, s, n) ((x) << (n)) | ((x) >> ((s) - (n))) #define ROTATE_RIGHT(x, s, n) ((x 阅读全文
posted @ 2012-05-20 16:26 Mr.Rico 阅读(2539) 评论(0) 推荐(0) 编辑
摘要:题目:要求一个数组连续下标和的最大值,数组的元素可正、可负、可为零,例如-2,5,3,-6,4,-8,6将返回8。这题是很经典的一道面试题,也有各种解法,从算法分析上,时间复杂度也有很大差别,下面我就给出三种不同的解法。方法一:暴力枚举法此种方法最简单,我想应该也是每个人拿到题目想到的第一种解法了,学过一点编程的人都应该能编出此类程序。记sum[i..j]为数组中第i个元素到第j个元素的和(其中0<=i<j<=n-1),通过遍历所有的组合之和,就能找到最大的一个和了。伪代码如下:int maxSubArray(int *A,int n) { int maxium = -INF 阅读全文
posted @ 2012-05-17 15:21 Mr.Rico 阅读(13396) 评论(2) 推荐(3) 编辑
摘要:计算某一天是星期几的公式如下: W = (Y-1) + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D.其中Y是年份,D是改天是Y年的第几天。具体的解释见这儿 具体代码如下:#include<iostream>#include<string>#include<sstream>usingnamespacestd;constintMONTH[12]={31,28,31,30,31,30,31,31,30,31,30,31,};conststringWEEK[]={"SUN","MON", 阅读全文
posted @ 2012-05-17 00:00 Mr.Rico 阅读(579) 评论(0) 推荐(0) 编辑
摘要:总结一下一些常用的计算平方根的方法1. 牛顿法具体的做法如下: 计算公式如下:具体的计算程序如下: doublesqrt_(doublex){doubleg=x;while(ABS(g*g-x)>0.000001){g=(g+x/g)/2;}returng;}2. 利用级数进行逼近微积分中的泰勒级数如下:这样,有了这个公式我们可以得到求平方根公式的展开式: 这样我们可以进行在一定精度内的逼近。但是这儿存在一个问题,就是这个公式的收敛问题。它是存在收敛区间的。 所以可以得到最后的代码:doubleTsqrt(doublex)//计算[0,2)范围内数的平方根{doublesum,coffe 阅读全文
posted @ 2012-05-15 22:34 Mr.Rico 阅读(37976) 评论(0) 推荐(0) 编辑
摘要:部分内容来自互联网: 【问题描述】对于一个栈,已知元素的进栈序列,判断一个由栈中所有元素组成的排列是否是可能的出栈序列。 比如,进栈序列为1 2 3 4,则可能的出栈序列有4 3 2 1,1 4 3 2等。而1 4 2 3就不是。 【输入形式】从标准输入读取第一行是一个整数N(3≤N≤10),代表有N个元素,其进栈序列是1 2 3 …… N。 第二行是空格分隔的1~N的数字的一个排列。 【输出形式】向标准输出打印结果。如果该排列是可能的出栈序列,则打印“YES”, 否则打印“NO”。在行末要输出一个回车符。 【输入样例】 3 3 1 2 【输出样例】 NO 【样例说明】进栈序列为1 2 3.. 阅读全文
posted @ 2012-05-07 15:07 Mr.Rico 阅读(1854) 评论(0) 推荐(0) 编辑
摘要:约瑟夫环问题:有编号从1到N的N个人坐成一圈报数,报到M的人出局,下一位再从1开始, 如此持续,直止剩下一位为止,报告此人的编号X。输入N,M,求出X。对于这个问题,有很多解法。包括一些基本的解法和一些优化的算法。基本解法一:这个方法比较直观,就是使用循环列表来模拟约瑟夫环。但是复杂度比较高,为O(m*n) 具体的代码如下:View Code /**=====================================================================================**Filename:c069_2.c**Description:**Ver. 阅读全文
posted @ 2012-02-26 12:49 Mr.Rico 阅读(363) 评论(0) 推荐(0) 编辑
摘要:昨天看到了一些比较巧妙的算法,觉得挺不错的。参考:http://blog.csdn.net/csdn_zc/article/details/67769291. 素数判断作者给出了几种方法。方法一:View Code intisPrime(intn)//函数返回1表示是质数,返回0表示不是质数{inti;for(i=2;i<n;i++)if(n%i==0)return0;return1;}这个是最原始的做法:从2开始,检测数n是否能被其之前的任意一个数整除,如果能,说明其不是素数。方法二:View Code intisPrime(intn){inti;for(i=2;i*i<n;i+ 阅读全文
posted @ 2012-02-11 11:00 Mr.Rico 阅读(973) 评论(0) 推荐(0) 编辑
摘要:假设这有一个各种字母组成的字符串,假设这还有另外一个字符串,而且这个字符串里的字母数相对少一些。从算法是讲,什么方法能最快的查出所有小字符串里的字母在大字符串里都有? 解答: (1)把其中的每个字母都放入一个Hashtable里(成本是O(n)或16次操作)。然后轮询第二个字串,在Hashtable里查询每个字母,看能否找到。如果找不到,说明没有匹配成功。 (2) 假设我们有一个一定个数的字母组成字串 —— 我给每个字母分配一个素数,从2开始,往后类推。这样A将会是2,B将会是3,C将会是5,等等。现在我遍历第一个字串,把每个字母代表的素数相乘。你最 终会得到一个... 阅读全文
posted @ 2012-02-03 16:14 Mr.Rico 阅读(4808) 评论(0) 推荐(0) 编辑
摘要:这涉及到概率 分布的内容了,其实也简单只要能找到一个概率为1/2p的函数就解决了. 另外还有一个比较方便的实现: 一随机数f(x)以概率 p 生成0, 那么设g(x)=f(x)>0?0:1; 刚g(x)以概率 1-p 生成0. 所以f(x),g(x)同时生成0的概率为p(1-p)等于同时生成1的概率. 得等概率随机数 function g(x){ int v=f(x)+g(x); if(v==0){ return 0; //1.f(x)g(x)同时为0 else if(v==2){ return 1; //2.f(x)g(x)同时为1 }else{ ... 阅读全文
posted @ 2011-10-14 22:47 Mr.Rico 阅读(1237) 评论(0) 推荐(0) 编辑