小甲鱼老师的数据结构与算法是以C为基础的,统计出身,没有学过C,就换了其他的课来听啦。现在听的是MOOC上北大的课,以python为基础的。
问题描述:
变位词是指两个词之间存在组成字母重新排列关系,如heart和earth,python和typhon。
为了简单起见,假设参与判断的两个词仅由小写字母构成,而且长度相等。
解题目标:写一个bool函数,以两个词作为参数,返回这两个词是否变位词,可以很好地展示同一问题的不同数量级算法
解法一:逐字检查
代码:
算法分析:
问题规模:词中包含的字符个数
主要部分在于两重循环
外层循环遍历s1每个字符,将内层循环执行n次;而内层循环在s2中查找字符,每个字符的对比次数,分别是1、2……n中的一个,而且各不相同
所以总执行次数是1+2+3+……+n=1/2n^2
+1/2n→O(n^2)。
解法2:排序比较
解题思路:
将两个字符串都按照字母顺序排好序,再逐个字符对比是否相同,如果相同则是变位词,有任何不同就不是变位词。
代码:
算法分析:
粗看上去,本算法只有一个循环,最多执行n次,数量级是O(n)。但循环前面的两个sort并不是无代价的。从后面的学习内容可以知道,排序算法采用不同的解决方案,其运行时间数量级差不多是O(n^2)或者O(nlogn),大过循环的O(n)。所以本算法时间主导的步骤是排序步骤,本算法的运行时间数量级就等于排序过程的数量级O(nlogn)
解法3:暴力法
解题思路:
穷尽所有可能组合,将s1中出现的字符进行全排列,再查看s2是否出现在全排列列表中。这里最大的问题是产生s1所有字符的全排列(n!个)。
算法分析:
已知n!的增长速度甚至超过2^n,暴力法不是个好方法。
解法4:计数比较
解题思路:
对比两个词中每个字母出现的次数,如果26个字母出现的次数都相同的话,这两个字符串就一定是变位词。
具体做法:
为每个词设置一个26位的计数器,先检查每个词,在计数器中设定好每个字母出现的次数。计数完成后,进入比较阶段,看两个字符串的计数器是否相同,如果相同则输出是变位词的结论。
代码:
算法分析:
计数比较算法中有3个循环迭代,但不像解法1那样存在嵌套循环。前两个循环用于对字符串进行计数,操作次数等于字符串长度n,第3个循环用于计数器比较,操作次数总是26.所以总操作次数T(n)=2n+26,其数量级为O(n)。
这是一个线性数量级的算法,是4个变位词判断算法中性能最优的。
中文变位词例子:“不可随处小便”,“小处不可随便”