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