现在的位置: 首页 > 综合 > 正文

Chapter 1 | Arrays and Strings — 判断字符串中字符唯一

2014年07月11日 ⁄ 综合 ⁄ 共 1241字 ⁄ 字号 评论关闭

1.1    Implement an algorithm to determine if a string has all unique characters.What if you can not use additional data structures?

译文:实现一个算法来判断字符串中的字符是否唯一,不能使用额外的数据结构,即只可使用基本的数据结构

首先,假定该字符集是含扩展的ASCII字符(256个),可以开一个大小为256的bool数组来表征字符的出现,鉴于每个字符的ASCII码值是唯一的,则可以将该字符的值设定为数组的位置,初始化数组为false(表示没出现过),遍历一遍字符串,判断是否之前出现过该字符,如果没有,则将对应位置为true,表示已经出现了,否则表示已经出现过。

bool isUnique(string str)
{
	bool a[256];
	menset(a, 0, sizeof(a));
	
	int len = string.lenth();
	for (int i = 0; i < len; ++i)
	{
		int loc = (int)str[i];
		if ( a[loc] )
			return false;
		a[loc] = true;
	}
	return true;
}

判断唯一的方法可以采用“值置换为位置的方法”,前提是该值是唯一的。

上述算法的空间复杂度为O(n),我们可以进一步优化,对于ASCII字符,我们只需要256位,为此我们可以开设一个长度为8的int型数组,正好256位(4*8*8),接下来就是考虑如何将字符唯一的映射到数组中去。我们可以把这个长度为8的int型数组看成是8*32的二维数组,来确定各字符的映射位置。例如'a'的ASCII值为97,用97除32的值作为行数,即数组的下标,用97对32取的模作为列数,即下标中的对应位。基本原理和上面是一样的

bool isUnique(string str)
{
	int len = str.length();
	int a[8];
	memset(a, 0, sizeof(a));

	for (int i = 0; i < len; ++i)
	{
		int v = (int)str[i];
		int index = v / 32, shift = v % 32;

		if (a[index] & (1 << shift))
			return false;
		a[index] |= (1 << shift);
	}
	return true;
}

如果字符时介于a-z(A-Z)之间,那就更方便了,只需至少26位的空间即可,进行位运算只需要一个整型数。

bool isUnique(string str)
{
	int check = 0;
	int len = str.length();

	for (int i = 0; i < len; ++i)
	{
		int shift = (int)(str[i] - 'a');
		if (check & (1 << shift))
			return false;
		check |= (1 << shift);
	}
	return true;
}

判断某个值的唯一,用值代替位置是一个不错的方法。另外进一步扩展,也可以用于计算某个值出现的次数,基本思想不变只需修改一下条件下的实现即可。

抱歉!评论已关闭.