另外,有大牛已经将java代码翻译成了C++代码,对于此系列的文章的较好的设计思路,也会用Java代码进行实现。查看地址:http://hawstein.com/posts/ctci-solutions-contents.html
言归正传,下面看第一个题目:
Implement an algorithm todetermine if a string has all unique characters. What if you can not useadditional data structures?
不使用额外的数据结构,实现一个算法用来判断一个字符串是否只有唯一的字符串组成。
首先要考虑构成字符串的字符集多大,是ASCII字符还是只有26个字母,对于不同的字符集处理的办法也不相同。
以ASCII字符为例,最先想到的办法是初始化一个256的bool数组,遍历字符串,对于每一个元素,检查在字符串中是否存在,存在即返回false,不存在继续查找。代码如下
public static boolean isUnique(String str) {
if (str == null || str.trim().length() == 0) {
return false;
}
str = str.trim();
boolean[] arr = new boolean[256];
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
// 检查当前字符是否已经存在
if (arr[c]) {
return false;
} else {
arr[c] = true;
}
}
return true;
}
不论被检查的字符串多长,空间使用量都是256*2个字节,我们可以通过位运算减少空间的使用量。Int由32位组成,对于ASCII的256个字符,可以映射到8个int元素中。我们规定如下,被8整除的字符使用一个int值,被8除余1的元素使用一个元素,……
代码如下
public static boolean isUnique3(String str)
{
if (str == null || str.trim().length() == 0) {
return false;
}
str = str.trim();
// 8个元素的int数组可以表示整个ASCII字符集
int[] arr = new int[8];
for(int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
int index = c / 32; // 寻找该字符所在的元素
int offset = c % 32; // 寻找字符在元素的位置
if((arr[index] & ( 1 << offset )) > 0)
{
return false;
}
else
{
arr[index] |= 1 << offset;
}
}
return true;
}
使用位运算后,该算法的空间复杂度维持O(n)不变,空间占用下降为4*8=32个字节。
如果字符只涉及到a-z的小写字母,使用位运算只使用一个int值即可。
/**
* 默认字符只有小写字母,可以将a-z映射到1-26位,对每个字符进行检查,是否该字符已经存在
*
* @param str
* @return
*/
public static boolean isUnique2(String str) {
if (str == null || str.trim().length() == 0) {
return false;
}
int checker = 0;
str = str.trim();
for (int i = 0; i < str.length(); i++) {
int c = str.charAt(i) - 'a'; // 获取当前字符应该映射的位数
// 检查该字符是否存在
if ((checker & (1 << c)) > 0) {
return false;
} else {
checker |= 1 << c; // 将该字符的对应的位数置为1
}
}
return true;
}
今天是第一次写该系列的文章,后边要好好坚持下去,加油。