易位词的匹配

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

来源于一道微软面试题,如下

两个单词如果包含相同的字母,次序不同,则称为字母易位词(anagram).例如, silent和listen是字母易位词,而apple和aplee不是易位词.请定义函数,检查两个单词是否是字母易位词.可以假设两个单词字母均为小写.要求算法复杂度尽量低.

 

观察易位词,发现三个特点

1, 长度相同;

2, 前面单词出现过的字母,也一定在后面的单词中出现过;

3, 同一个字母在前面和后面的单词中出现的次数相同;

 

思路一

对前面单词的每个字母进行循环遍历,看是否在后面出现过,如果出现过,则将出现的那个字母删除,然后进行下一次循环.这里用PHP来实现.

//将一个单词转化为数组
function wordToArray($str=''){
	$str = is_string($str) ? trim($str) : trim($str.'');
	$len = strlen($str);
	$arr = array();
	if($len>0){
		for($i=0;$i<$len;$i++){
			$arr[]=$str[$i];
		}
	}
	return $arr;
}

//检查两个字符串是否互为字母易位词
function checkAnagram($a='',$b=''){

	//强制转换为字符串
	$a = is_string($a) ? trim($a) : trim($a.'');
	$b = is_string($b) ? trim($b) : trim($b.'');
	
	//转化为数组
	$a = wordToArray($a);
	$b = wordToArray($b);

	//检查字符串长度
	$len1 = count($a);
	$len2 = count($b);

	if($len1 != $len2){
		return false;
	}

	//对第一个字符串进行循环遍历
	for($i=0;$i<$len1;$i++){
		//相同次数初始化
		$sameTime = 0;
		//对第二个字符串进行遍历
		for($j=0;$j<$len2;$j++){
			//如果第一个字符串中某个字母在第二个字符串中被第一次找到
			if($a[$i] === $b[$j]){
				//如果找到相同的字母+1
				$sameTime++;
				//则将第二个字符串中的该字母删除,也就是用空字符串将其替代
				unset($b[$j]);
				//删除后不继续往下遍历,开始第一个字符串中下一个字母的循环遍历
				break;
			}
		}
		//如果遍历玩第二个单词一次相同的字母都没有找到则为否
		if(empty($sameTime)) return false;
	}
	//如果第二个字符串的所有字母都被删除了,说明第一个字符串中的字母都在第二个字符串中且出现次数相等
	return empty($b) ? true : false;
}

用 silent和listen做测试

$a = checkAnagram('silent','listen');
var_dump($a);

结果为真

/opt/wwwroot/test/test7.php:157:boolean true

用 apple和aplle做测试,结果为否

/opt/wwwroot/test/test7.php:157:boolean false

测试OK

 

思路二

易位词组成的字母是相同的,只是顺序不同,如果按照字母顺序排序后,两者应该完全一样.

//将一个单词转化为数组
function wordToArray($str=''){
	$str = is_string($str) ? trim($str) : trim($str.'');
	$len = strlen($str);
	$arr = array();
	if($len>0){
		for($i=0;$i<$len;$i++){
			$arr[]=$str[$i];
		}
	}
	return $arr;
}

function checkAnagram($a='',$b=''){
	//强制转换为字符串
	$a = is_string($a) ? trim($a) : trim($a.'');
	$b = is_string($b) ? trim($b) : trim($b.'');
	
	//转化为数组
	$a = wordToArray($a);
	$b = wordToArray($b);

	//检查字符串长度
	$len1 = count($a);
	$len2 = count($b);

	if($len1 != $len2){
		return false;
	}

	//对两个单词的字母按字母顺序排序,返回排序后的新数组
	sort($a);
	sort($b);

    //如果两个数组相同,返回真
	return ($a==$b)? true : false;
}

用 silent 和 listen 测试,返回真

$a = checkAnagram('silent','listen');
var_dump($a);
/opt/wwwroot/test/test7.php:183:boolean true

用 apple 和 aplle 测试,返回否

$a = checkAnagram('apple','aplle');
var_dump($a);
/opt/wwwroot/test/test7.php:184:boolean false

比方法一更轻松些

 

思路三

易位词的字母组成是一样的并且字母出现的次数一致,那么可以对每个字母做计数,然后对比两组计数,相同则为真

function checkAnagram($str1='',$str2=''){
	//强制转换为字符串
	$str1 = is_string($str1) ? trim($str1) : trim($str1.'');
	$str2 = is_string($str2) ? trim($str2) : trim($str2.'');

	//检查字符串长度
	$len1 = strlen($str1);
	$len2 = strlen($str2);

	if($len1 != $len2){
		return false;
	}

	//字符串计数器初始化
	$arr1 = $arr2 = array();

	//对第一个字符串做遍历计数
	for($i=0;$i<$len1;$i++){
		//获取字母在字母表中的位置
		$pos = ord($str1[$i]) - ord('a');
		//每出现一次就在该位置上计数+1
		$arr1[$pos] +=1;
	}

	//对第二个字符串做遍历计数
	for($j=0;$j<$len1;$j++){
		//获取字母在字母表中的位置
		$pos = ord($str2[$j]) - ord('a');
		//每出现一次就在该位置上计数+1
		$arr2[$pos] +=1;
	}

	//对两个数组做比较
	return ($arr1==$arr2)? true : false;
}

用 silent 和 listen 测试,返回真

$a = checkAnagram('silent','listen');
var_dump($a);
/opt/wwwroot/test/test7.php:183:boolean true

用 apple 和 aplle 测试,返回否

$a = checkAnagram('apple','aplle');
var_dump($a);
/opt/wwwroot/test/test7.php:184:boolean false

 

比较三种思路的计算量

第一种思路是遍历里面再次遍历,一共有n(n+1)/2次运算,复杂度为O(n^2);

第二种思路看起来只是对每个字母做了一次比较,也就是n个计算量.但实际上在比较之前,分别对两个字符串做了排序处理,把排序运算包括进去后就是(n*logn+n)次运算,复杂度为O(n*logn);

第三种思路分别对字符串进行了遍历,最后进行了一次比较,所以计算量为min(n+n+n, n+n+26),复杂度为O(n);

 

算法复杂度

算法复杂度是指算法在编写成可执行程序后,运行时所需要的资源,资源包括时间资源和内存资源。应用于数学和计算机导论。同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。一个算法的评价主要从时间复杂度和空间复杂度来考虑。

若要独立于机器的软、硬件系统来分析算法的时间耗费,则设每条语句执行一次所需的时间均是单位时间,一个算法的时间耗费就是该算法中所有语句的频度之和。

求两个n阶方阵的乘积 C=A×B,其算法如下:

# define n 100 // n 可根据需要定义,这里假定为100
void MatrixMultiply(int A[n][n],int B [n][n],int C[n][n])
{ //右边列为各语句的频度
    int i ,j ,k;
    for(i=0; i

T(n)=2n3+3n2+2n+1 (1.1)该算法中所有语句的频度之和(即算法的时间耗费)为:

分析:

语句(1)的循环控制变量i要增加到n,测试到i=n成立才会终止。故它的频度是n+1。但是它的循环体却只能执行n次。语句(2)作为语句(1)循环体内的语句应该执行n次,但语句(2)本身要执行n+1次,所以语句(2)的频度是n(n+1)。同理可得语句(3),(4)和(5)的频度分别是n2,n2(n+1)和n3。

算法MatrixMultiply的时间耗费T(n)是矩阵阶数n的函数。

 

思考

忽然想起了廖老师.

转载于:https://my.oschina.net/u/3412738/blog/1551323

你可能感兴趣的:(易位词的匹配)