??xml version="1.0" encoding="utf-8" standalone="yes"?> 数组a[N]Q?至N-1qN-1个数存放在a[N]中,其中某个数重复一ơ。写一个函敎ͼ扑և被重复的数字?/p>
Ҏ(gu)一Q异或法?/p>
数组a[N]中的N个数异或l果?至N-1异或的结果再做异或,得到的值即为所求?/p>
代码Q?/p>
Ҏ(gu)二:数学法?/p>
Ҏ(gu)l的所有项求和Q减?至N-1的和Q即为所求数?/p>
对于求和Q可以直接根据公式定义一个宏?define sum(x) (x*(x+1)/2) Ҏ(gu)三:标志数组?/p>
甌一个长度ؓn-1且均?0'l成的字W串。然后从头遍历a[n]数组Q取每个数组元素a[i]的|其对应的字W串中的相应位置|?Q如果已l置q?的话Q那么该数就是重复的数。就是用位图来实现的?如果考虑I间复杂度的话,其空间OQNQ?/p>
Ҏ(gu)四:固定偏移量法 a[N]Q里面是1至N-1。原数组a[i]最大是N-1Q若a[i]=K在某处出现后Q将a[K]加一ơNQ做标记Q当某处a[i]=K再次成立Ӟ查看a[K]卛_知道K已经出现q。该Ҏ(gu)不用另外开辟O(N)的内存空_但是在查重之后要数l进行恢复?/p>
Ҏ(gu)五:W号标志?/p>
上个Ҏ(gu)出现后是加NQ也可以出现后加个负P是W号标志法?/p>
以上的方法对数组元素的值的范围是有限制的,如果数组元素的g是在1至N-1范围Ӟ可以先求出数l元素的最大倹{?/p>
转:http://buptdtt.blog.51cto.com/2369962/749049 "快速排?的思想很简单,整个排序q程只需要三步: Q?Q在数据集之中,选择一个元素作?基准"QpivotQ?/p>
Q?Q所有小?基准"的元素,都移?基准"的左边;所有大?基准"的元素,都移?基准"的右辏V?/p>
Q?Q对"基准"左边和右边的两个子集Q不断重复第一步和W二步,直到所有子集只剩下一个元素ؓ止?/p> 举例来说Q现在有一个数据集{85, 24, 63, 45, 17, 31, 96, 50}Q怎么对其排序呢? W一步,选择中间的元?5作ؓ"基准"。(基准值可以Q意选择Q但是选择中间的值比较容易理解。) W二步,按照序Q将每个元素?基准"q行比较QŞ成两个子集,一?于45"Q另一?大于{于45"?/p>
W三步,对两个子集不断重复第一步和W二步,直到所有子集只剩下一个元素ؓ止?/p>
下面参照|上的资料(q里?a target="_blank">q里Q,用Javascript语言实现上面的算法?/p>
首先Q定义一个quickSort函数Q它的参数是一个数l?/p>
var quickSort = function(arr) { }; 然后Q检查数l的元素个数Q如果小于等?Q就q回?/p>
var quickSort = function(arr) { if (arr.length <= 1) { return arr; } }; 接着Q选择"基准"QpivotQ,q将其与原数l分,再定义两个空数组Q用来存放一左一右的两个子集?/p>
var quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2) ; var pivot = arr.splice(pivotIndex, 1)[0]; var left = []; var right = []; }; 然后Q开始遍历数l,于"基准"的元素放入左边的子集Q大于基准的元素攑օ双的子集?/p>
var quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2) ; var pivot = arr.splice(pivotIndex, 1)[0]; var left = []; var right = []; for (var i = 0; i < arr.length; i++){ if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } }; 最后,使用递归不断重复q个q程Q就可以得到排序后的数组?/p>
var quickSort = function(arr) { if (arr.length <= 1) { return arr; } var pivotIndex = Math.floor(arr.length / 2); var pivot = arr.splice(pivotIndex, 1)[0]; var left = []; var right = []; for (var i = 0; i < arr.length; i++){ if (arr[i] < pivot) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat([pivot], quickSort(right)); }; 使用的时候,直接调用quickSort()p了? Q完Q?br />
]]>
]]>
快速排序的基本思想Q?/p>
通过一排序将待排序记录分割成独立的两部分Q其中一部分记录的关键字均比另一部分关键字小Q则分别对这两部分l进行排序,直到整个序列有序?/p>
先看一下这q图Q?/p>
把整个序列看做一个数l,把第零个位置看做中uQ和最后一个比Q如果比它小交换Q比它大不做M处理Q交换了以后再和的那端比,比它?yu)不交换Q比他大交换。这样@环往复,一排序完成,左边是比中轴小的,双是比中轴大的,然后再用分治法,分别对这两个独立的数l进行排序?/p>
2 3 7 10 14 23 34 53
q样排序好了,快速排序是对冒泡排序的一U改q,q_旉复杂度是O(nlogn)?br />
我想说一?#8220;我日Q我讨厌KMPQ?#8221;?br />KMP虽然l典Q但是理解v来极其复杂,好不Ҏ(gu)理解好了Q便L(fng)来巨ȝQ?br />老子是今天图书馆在写了几个时才勉强写了一个有bug的、效率不高的KMPQ特别是计算next数组的部分?br />
其实Q比KMP法速度快的法大把大把Q而且理解h更简单,Z非要抓住KMP呢?W试出现字符串模式匹配时直接上sunday法Q既单又高效Q何乐而不为?
说实话,惛_sunday法的那个hQ绝Ҏ(gu)发散思维Q绝对牛。当我在被KMP折磨的够呛的时候,我就琢磨Q有没有别的好算法呢Q?琢磨了半天也没想Z所以然来。笨啊,脑子不够发散?br />
下面贴上一位兄弟写的算法ȝQ很单(KMP部分׃用看了,看了费脑子)?br />参见Q?a >http://hi.baidu.com/willamette/blog/item/02bd0b5599c8b4c0b645ae06.html
着做Presentation的功夫,Z做一个ȝ
字符串匹配:
---willamette
在匹配串中寻找模式串是否出现Q注意和最长公共子序列相区?span style="font-family: Times New Roman">(LCS: Longest Common Substring)
-Q?/strong>Brute Force(BF或蛮力搜?法Q?/strong>
q是世界上最单的法了?br />首先匹配串和模式串左对齐,然后从左向右一个一个进行比较,如果不成功则模式串向右移动一个单位?/p>
速度最慢?/p>
那么Q怎么改进呢?
我们注意?span style="font-family: Times New Roman">Brute Force法是每ơ移动一个单位,一个一个单位移动显然太慢,是不是可以找C些办法,让每ơ能够让模式串多Ud一些位|呢Q?/p>
当然是可以的?/p>
我们也注意到Q?span style="font-family: Times New Roman">Brute Force是很?span style="font-family: Times New Roman">intelligent的,每次匚w不成功的时候,前面匚w成功的信息都被当作废物丢弃了Q当Ӟ如现在的变废ؓ宝一P我们也同样可以将前面匚w成功的信息利用v来,极大地减计机的处理时_节省成本?span style="font-family: Times New Roman">^_^
注意Q蛮力搜索算法虽焉度慢,但其很通用Q文章最后会有一些更多的关于蛮力搜烦的信息?/span>
-: KMP法
首先介绍的就?span style="font-family: Times New Roman">KMP法?/p>
原始论文Q?span style="font-family: Times New Roman">Knuth D.E., Morris J.H., and Pratt V.R., Fast pattern matching in strings, SIAM Journal on Computing, 6(2), 323-350, 1977.
q个法实在是太有名了,大学上的法评除了最W的Brute Force法Q然后就介绍?span style="font-family: Times New Roman">KMP法。也难怪,呵呵。谁?span style="font-family: Times New Roman">Knuth D.E.q么world famous呢,不仅拿了囄奖,而且q写Z计算机界?span style="font-family: Times New Roman">Bible <The Art of Computer Programming>(业内人士一般简U?span style="font-family: Times New Roman">TAOCP).E稍提一下,有个?span style="font-family: Times New Roman">H.A.Simon的家伙,不仅拿了Turing AwardQ顺手拿了个Nobel Economics AwardQ做?span style="font-family: Times New Roman">AI的爸爸,q是Chicago Univ?span style="font-family: Times New Roman">Politics PhDQ可谓全才?/p>
KMP的具体描q略去,教科书一大把?/span>
-QHorspool法
Horspool法?/p>
当然Q有市场有竞争Q字W串匚wq么大一个市场,不可能让BF?span style="font-family: Times New Roman">KMP全部占了Q于是又出现了几个强劲的Ҏ(gu)?/p>
W一个登场的?/p>
论文Q?span style="font-family: Times New Roman">Horspool R.N., 1980, Practical fast searching in strings, Software - Practice & Experience, 10(6):501-506
Horspool法的思想很简单的。不q有个创C处就是模式串是从叛_左进行比较的。很好很强大Qؓ后来的算法媄响很大?/p>
匚wԌabcbcsdxzcxx
模式Ԍcbcac
q个时候我们从叛_左进行对暗号Q?span style="font-family: Times New Roman">c-cQ恩对上了,W二?span style="font-family: Times New Roman">b-aQ不对啊Q我们应该怎么办?Np么放弃么。于是,模式串从不匹配的那个字符开始从叛_左寻扑配串中不匚w的字W?span style="font-family: Times New Roman">b的位|,l果发现居然有,赶快对上赶快对上Q别耽误了?/p>
匚wԌabcbcsdxzcxx
模式Ԍ cbcac
然后l箋从最双的字W从叛_左进行比较。这时候,我们发现了,d-c不匹配啊Q而且模式IK面没有噢Q没办法Q只好移动一个模式串长度的单位了?/p>
匚wԌabcbcsdxzcxx
模式Ԍ cbcac
-QBoyer-Moore法
对于BM法Q下面推荐一个讲解非怼U的文章,可谓图文q茂啊,而且q是个MM写的?/p>
Boyer-Moore l典单模式匹配算?br />http://blog.csdn.net/iJuliet/archive/2009/05/19/4200771.aspx
-QSunday法
最后一个是Sunday法Q实际上?span style="font-family: Times New Roman">Boyer-Mooreq快Q呵c长江后推前浪?/p>
原始论文Q?span style="font-family: Times New Roman">Daniel M. Sunday, A very fast substring search algorithm, Communications of the ACM, v.33 n.8, p.132-142, Aug. 1990
看原始论文的题目Q?span style="font-family: Times New Roman">D.M. Sunday貌似是故意想气气Boyer-Moore两位大牛似的。呵c不q实际上的确Sunday法的确?span style="font-family: Times New Roman">BM法要快Q而且更简单?/p>
Sunday的算法思想?span style="font-family: Times New Roman">Horspool有些怼Q但是。当出现不匹配的时候,却不是去扑配串中不匚w的字W在模式串的位置Q而是直接找最双寚w的右一位的那个字符在模式串的位|?/p>
比如Q?/p>
匚wԌabcbczdxzc
模式Ԍzbcac
恩,q里我们看到b-a没有对上Q我们就看匹配串中的z在模式串的位|,然后Q嘿ѝ?/p>
匚wԌabcbczdxzc
模式Ԍ zbcac
如果模式串中的没有那个字W怎么办呢Q很单,跌d?/p>
匚wԌabcbcedxzcs
模式Ԍzbcac
e不在模式串中出现
那么我们?/p>
匚wԌabcbcedxzcs
模式Ԍ zbcac
(2009/10/20补充)
RK法
某一天在图书馆的一本算法分析设计书上翻到的。思\很新颖!和大家分享下?br />在串匚w的简单算法中Q把文本每m个字W构成的字符D作Z个字D,和模式进行匹配检查。如果能对一个长度ؓm的字W?/p>
串赋以一个Hash函数。那么显然只有那些与模式h相同hash函数值的文本中的字符串才有可能与模式匚wQ这是必要条?/p>
Q而没有必要去考虑文本中所有长度ؓm的字D,因而大大提高了串匹配的速度。因此RK法的思想和KMPQBMQSunday{?/p>
路E然不同!
Q事实上Q之前的串匹配方法,是将模式串的一个一个字W作为小的特征去分别q行匚wQ而RK法则是串整体作ؓ一?/p>
特征Q难难在单个字W的特征很容易想得到Q整体作Z个特征就没那么容易想得到了)
如果把整体作Z个特征,那么如何快速的求出q个整体特征的特征|Q?br />模式串的特征g需求一ơ即可。对于文本中的Q意m个字W构成的字串如何快速的求特征就是个隄了?br />抛砖引玉Q这里给Z个简单的特征计算?字W串的每一个字W看做一个数Q那么这个字W串的就是一个数字数l,?/p>
q积分向量可以快速Q意一个长度子字符串的向量和。可以把字符串的对应的字W数l的元素和看做这个字W串整体特征?/p>
q个特征是可以再OQ?Q的旉内求出的。其实原始的RK法里面是把字符串看做一?6q制数在计算特征的。这里就不啰
嗦了Q有兴趣的可以深入查?/p>
aabseesds 模式?ees
ees
发现 see向量?== ees的向量和
然后对see和ees做逐个字符的比较。发C匚wl箋往下走
aabseesds 模式?ees
ees
发现 ees向量?== ees的向量和
然后对ees和ees做逐个字符的比较。发现匹配OK?br />
另外q有 字符串匹配自动机 后缀树算法(分在U和非在U两U){?见如下文章。不能说那个比那个更好,各个法都有自己的优势及最?jng)_用场合。参考:
http://blog.csdn.net/yifan403/archive/2009/06/16/4272793.aspx
另外Q关于多模式字符串匹?有AC法Q字W串匚w自动机思想Q?WM法QBM在多模式的推q应用)
参考:
http://blog.csdn.net/ijuliet/category/498465.aspx 该女子的blog有很多好文章?br />
===============================================================================
一个sunday法的实?br />http://hi.baidu.com/azuryy/blog/item/10d3d3460b97af0e6b63e5cd.html
头文件定义:
/* Sunday.h */
class Sunday
{
public:
Sunday();
~Sunday();
public:
int find(const char* pattern, const char* text);
private:
void preCompute(const char* pattern);
private:
//Let's assume all characters are all ASCII
static const int ASSIZE = 128;
int _td[ASSIZE] ;
int _patLength;
int _textLength;
};
源文?br />/* Sunday.cpp */
Sunday::Sunday()
{
}
Sunday::~Sunday()
{
}
void Sunday::preCompute(const char* pattern)
{
for(int i = 0; i < ASSIZE; i++ )
_td[i] = _patLength + 1;
const char* p;
for ( p = pattern; *p; p++)
_td[*p] = _patLength - (p - pattern);
}
int Sunday::find(const char* pattern, const char* text)
{
_patLength = strlen( pattern );
_textLength = strlen( text );
if ( _patLength <= 0 || _textLength <= 0)
return -1;
preCompute( pattern );
const char *t, *p, *tx = text;
while (tx + _patLength <= text + _textLength)
{
for (p = pattern, t = tx; *p; ++p, ++t)
{
if (*p != *t)
break;
}
if (*p == 0)
return tx-text;
tx += _td[tx[_patLength]];
}
return -1;
}
单测试下Q?br />int main()
{
char* text = "blog.csdn,blog.net";
char* pattern = "csdn,blog" ;
Sunday sunday;
printf("The First Occurence at: %d/n",sunday.find(pattern,text));
return 1;
}
////////////////////////////////////////////
strstr的实现?br />需要说明的是strstr是c语言提供的用Brute Force实现的字W串匚wQ简单、通用是其最大的优点。时间复杂度是O(mn)
// 下面是Microsoft的实?br />//l典法
//比KMP法?没有KMP法高效
char * __cdecl strstr (
const char * str1,
const char * str2
)
{
char *cp = (char *) str1;
char *s1, *s2;
if ( !*str2 )
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *) str2;
while ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
本文来自CSDN博客Q{载请标明出处Q?a >http://blog.csdn.net/whoismickey/archive/2009/02/08/3869367.aspx