假设字符集是ASCII字符
解法一:使用一个长度为256的bool型数组,数组中的每一个元素与ASCII字符集中的字符相对应,数组最开始初始化为false,当处理一串字符时若某个字符所对应的数组中该位置的元素为true,则表示该字符已在前面出现,即这个字符串中的字符不唯一。如若所对应位置的元素为false,则将该元素赋值为true。然后在继续处理剩下的字符串。
bool isUniqueArray(char s[])
{
int length = strlen(s);
int i,j;
bool flag[256];
memset(flag,0,sizeof(flag));
for(i = 0; i < length; ++i)
{
j = (int)s[i];
if(flag[j])
return false;
flag[j] = true;
}
return true;
}
该算法的空间复杂度为O(n),可使用位运算来减少空间的消耗,由此得到解法二。
解法二:由于ASCII字符集有256个字符,因此需要使用256个位的数来表示,一个int类型是32位的,因此使用长度为256/32 = 8的bitflag整型数组就可以表示256个字符集中的每个字符,即一位表示一个字符。
将256个字符集分为8个区域:[0-31]、[32-63]、[64-95]、[96-127]、[128-159]、[160-191]、[192-223]、[224-255],这8个区域分别与bitflag[0]、bitflag[1]、bitflag[2]、bitflag[3]、bitflag[4]、bitflag[5]、bitflag[6]、bitflag[7]相对应,bitflag中的每个元素是一个32位的int型数,因此int中的每一位可表示一个数,总共就可表示32个数。
关键操作在于对一个字符首先要判断它在bitflag中的位置i,然后在判断它在bitflag[i]的第几位上,这个可以通过相除和取余确定。假设num是字符对应的ASCII值,则id = num / 32为在bitflag中的位置, shift = num % 32表示在bitflag[id]中的位置 。
bool isUniqueBit(char s[])
{
int length = strlen(s);
int i,num;
int bitflag[8];
int id,shift;
memset(bitflag,0,sizeof(bitflag));
for(i = 0; i < length; ++i)
{
num = (int)s[i];
id = num / 32;
shift = num % 32;
if(bitflag[id] & (1 << shift))
return false;
bitflag[id] |= (1 << shift);
}
return true;
}
1 << shift把1左移shift位,然后在与bitflag[id]按位相与,只有当该字符先前出现过时结果才会为1,否则就为0;判断之后,若该字符以前没有出现,则将其加入到bitflag[id]中,即把bitflag[id]的第shift位赋值为1