随笔分类 - 算法
摘要:最短路算法用于求带权有向图中,两点之间的最近距离。它通过不断扩大已知的最短路径,直到最短路径覆盖终点为止。由下面的程序可以看书,它的时间复杂度为O(n^3)。下面举一简单例子说明最短路算法的步骤。想求v0到v7的最短路径,初始的时候,只知道v0距离自己的最短距离为0.使用一个close数组存储以求得与v0的最短距离,如未求得的复制为-1. 开始时,close[0]=0;(1)遍历close里面的点,找出所有与close点相邻但不在close里面的点。刚开始只有v0在close里面,与它相邻的点有v1、v2、v3。(2)找出这些点中,距离v0最近的一个点。例如点i是close里面的点,j是i的邻
阅读全文
摘要:看了一道笔试题,说有100W个数据,范围在0~65535之间,要求用最少的空间和最快的速度进行排序。刚开始的思路是,65535就是2^16,那首先要把数据类型定义为short。其次,要用最少的空间,那最好还是不用递归,那不用快排。不递归,速度又快,那肯定是堆排序了。O(n)的空间+O(nlogn)的时间。后来看了网上的人对于这题的评点,原来统计排序才是这一条件下的最优解。统计排序,又叫桶排序。它的原理非常简单。在知道数据大小范围的条件下,定义一个等于数据大小范围的数组。数组初始化为0,然后直接用数据作为数组下标统计数据个数,最后把统计数据从头到尾输出(升序),或者从尾到头输出(降序)即可。时间
阅读全文
摘要:如果程序中经常要对矩阵进行与或非等运算,可以把整型数组的矩阵转化成char型的bitmap,通过直接的位运算进行这些与或非操作会大大地提高效率。class bitmap{ char *buf;public: int buf_len;//buf的长度 int bit_len;//bitmap的位数 bitmap(int *group,int group_len){ bit_len=group_len; buf_len=group_len/8+1; buf=new char[buf_len]; memset(buf,0...
阅读全文
摘要:如何判断链表环的入口位置?一个指针从头开始单步走,一个指针从第一次相遇位置开始单步走,再相遇的位置就是环入口,证明如下:设链表头到环入口位置距离为a,入口位置到第一次相遇位置为b,相遇位置回到入口位置距离为c。1、每次走一步的慢指针走了s步,则快指针走了2s步。s=a+b。相遇时慢指针一定没走完一圈。2、快指针走的总步数为a+b+n(b+c),走到相遇位置,并走了n圈。因此a+b+n(b+c)=2*(a+b)a=n(b+c)-b=(n-1)(b+c)+c,也就证明了上面所提的方法。class linklist{public: int val; linklist *next; ...
阅读全文
摘要:二叉树结构struct BTnode{ char m_val; BTnode *m_pl,*m_pr;};class BT{ BTnode *m_proot; void create(BTnode *father,int k); void pre_travel_helper(BTnode *father); void post_travel_helper(BTnode *father); void mid_travel_helper(BTnode *father); void clear_BT_helper(BTnode *father);pub...
阅读全文
摘要:质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。1不是素数。一个非素数可以由几个素数因子相乘得到,这些因子一定小于这个数的开方,因此可通过这个性质求素数:void slow(int n){ int i; for(i=2;i<=n;++i){ int flag=1; for(int j=2;j<=sqrt(i);++j){ if(i%j==0){ flag=0; break; } } i...
阅读全文
摘要:胜者树和败者树都是完全二叉树,是树形选择排序的一种变型。每个叶子结点相当于一个选手,每个中间结点相当于一场比赛,每一层相当于一轮比赛。 不同的是,胜者树的中间结点记录的是胜者的标号;而败者树的中间结点记录的败者的标号。 胜者树与败者树可以在log(n)的时间内找到最值。任何一个叶子结点的值改变后,利用中间结点的信息,还是能够快速地找到最值。在k路归并排序中经常用到。 叶子节点相当于参赛选手,中间节点是比赛,比赛中败者记录在中间节点,胜者继续参加后面的比赛,直到根节点。根节点之上的一个节点用来记录最终胜者。 败者树的建立:在参赛者数组b[]的最后添加一位,存...
阅读全文
摘要:当排序内容太大,不足以全部放入内存进行内部排序,则可把排序内容按可用内存大小分割成多个文件,分别读取文件进行内排,排序结果继续写入文件。最后对所有文件进行归并排序合并成有序大文件。外部排序步骤:1、分割数据 2、分别内排 3、归并小文件// acm.cpp : Defines the entry point for the console application.//#include "stdafx.h"#pragma warning(disable: 4786)#include <iostream>#include <string>#include
阅读全文
摘要:https://github.com/iyjhabc/simple_algorithm1、快速排序 选择数组的其中一个元素(一般为第一个)作为分界pivot,用两个游标分别从后往前和从前往后扫描数组。先从后游标开始,当后游标所指的值比pivot小,则与pivot交换,后游标交换后才扫描前游标;当前游标所指值比pivot大,则与pivot交换。一次分组的结果是pivot前面的元素全部比pivot小,后面的全部比pivot大。既然对前后两部分继续调用分组函数即可完成排序。 下面的程序对上述过程做了优化,交换的时候直接把游标所指的值覆盖到pivot的位置上,覆盖后,原来游标所指的位置作为下一次的..
阅读全文
摘要:1、农场计数问题/*问题描述1、已知某农场中有一群鸡和兔子,总共有M个头和N只脚,计算总共有多少鸡和兔子l 要求实现函数int GetFowlsNum(int iHeadNum, int iFootNum, int *iChickenNum, int *iRabbitNum)【输入】 iHeadNum: 总共头的数量 iFootNum: 总共脚的数量【输出】 iChickenNum: 鸡的数量 iRabbitNum: 兔子的数量【返回】 0: 找到符合要求的鸡和兔子的数量 ...
阅读全文
摘要:注重搞清楚基础概念,为笔试做准备第一章:绪论,基本概念数据结构在计算机中的表示,成为存储结构。其中最小的单位是位。一般分为两种表示方法,对应两种存储结构:顺序结构与链式结构数据类型:一个值的集合以及定义在这个集合的值的一组操作时间复杂度:常量复杂度,线性O(n),平方,指数,对数等第二章:线性表-vector(顺序存储结构、线性表)-list(链式存储结构、线性链表)特点:1、有唯一的“开头”“结尾” 2、除了开头,其他元素都有唯一的“前驱” 3、除了结尾,都有唯一的后继线性表特点:两元素的存储位置物理相邻,因此可以随机存取线性链表特点:使用指针连接,分布存储。不能随机存取,但方便插入数据he
阅读全文
摘要:一、后缀树其实是把一个单词所有的后缀都加上的一棵经过合并简化的字典树(trie tree)。如"mississip",其实就是在字典树中插入了"mississip","ississip","ssissip",sissip","issip","ssip","sip","ip","p"。这棵字典树已经可以完成后缀树的功能,只是它的空间复杂度极高。二、后缀树就是把上面字典树中不同的分支合并成字符串三、如何在O(N
阅读全文
摘要:在所有具有性能优化的数据结构中,我想大家使用最多的就是hash表,是的,在具有定位查找上具有O(1)的常量时间。但hash table需要使用巨大的内存空间,显然在处理大数据时会显得力不从心。 bitmap可以有效地节省内存的使用,它的思想其实就是用1bit来代替一个index(通常是一个unsigned int)。比如我要对{1,5,7,2}这四个byte类型的数字做排序,该怎么做呢?我们知道byte是占8个bit位,其实我们可以将数组中的值作为bit位的key,value用”0,1“来标识该key是否出现过?下面看图:从图中我们精彩的看到,我们的数组值都已经作为byte中的key了,...
阅读全文
摘要:第八十一题:1、求数组中大于左边所有元素,小于右边素有元素的数。只能用一个额外数组。思路:从左往右遍历先把max记录在额外数组中。从右往左遍历记录当前min在一个变量中。对比min和max和当前即可。//复杂度O(n),2次迭代,使用1个数组void helper(int *a,int n){ int nowmax=a[0],nowmin=a[n-1]; int max[n]; for(int i=0;i<n;++i){ if(a[i]>nowmax)nowmax=a[i]; max[i]=nowmax; } for(int i=n-1...
阅读全文
摘要:第一题:把二分查找树转换为升序排序的双向链表。不能新建节点,只能改变树的指针。二分查找树:左小于父,右大于父。中序遍历就是升序遍历。中序遍历递归法:void showMidTree(BSTreeNode *pRoot){ if(pRoot!=NULL) { showMidTree(pRoot->m_pLeft); cout<<pRoot->m_nValue<<endl; showMidTree(pRoot->m_pRight); }}思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左 子树转换成一个排好序的...
阅读全文
摘要:第十一题:求二元树中两个节点最远的距离方法:使用递归函数求左右子树的深度。左子树深度+右子树深度=最大距离。int BinaryTreeNode::getDeep(int floor){//(也是形参传递参数,返回值传递结果) int leftDeep=this->m_pLeft!=NULL ? this->m_pLeft->getDeep(floor+1) : floor; int rightDeep=this->m_pRight!=NULL ? this->m_pRight->getDeep(floor+1) : floor; return leftDe
阅读全文
摘要:第二十一题:输入m、n,打印出1~n中所有和等于m的组合(01背包问题)递归法:void printSolution(int *flag){ for(int i=1;i<100;++i) if(flag[i]!=0)cout<<i<<" "; cout<<endl;}void bao(int m,int n,int *flag){ if(m<1 || n<1)return; if(n>m)n=m; if(n==m){//end , print it flag[n]=1; printSolution(flag); .
阅读全文
摘要:第三十六题:比赛排名void match(int w[][8],int *order,int *result,int n){ memcpy(result,order,n*sizeof(int)); int round=n; while(round>0){ for(int i=0,j=0;i<round;i+=2,++j){ if(w[result[i]][result[i+1]]==result[i])swap(i,j,result); else swap(i+1,j,result); }...
阅读全文
摘要:第四十三题:二叉树的非递归前中后序遍历前序遍历:void preorderShowTreeIterative(BSTreeNode *pRoot){ stack<BSTreeNode*> buf; buf.push(pRoot); while(!buf.empty()){ BSTreeNode *p=buf.top(); buf.pop(); cout<<p->m_nValue<<endl; if(p->m_pRight!=NULL)buf.push(p->m_pRight);//right first i...
阅读全文
摘要:第五十一题:输出所有和为n的连续正数序列方法1:从1遍历到n/2,算出所有sum,如果sum刚好等于n则输出,效率极低。方法2:用一个变量b标志连续序列的开头,e表示结尾。如果序列的sum<n,则e++;如果sum>n,则b++。复杂度O(n)void constSumSequence(int n){ int b=1,e=1,sum=1,bound=n/2+1; while(e<=bound){ if(sum==n){ for(int k=b;k<=e;++k)cout<<k<<" "; cout<<endl; .
阅读全文

浙公网安备 33010602011771号