程序员面试金典——1.1确定字符互异
2018年4月7日从今天开始正式看《程序员面试金典》
Solution1:
之前一直以为的这类题比较好的一种方法,但貌似还是不太符合题目要求的“不要使用额外的存储结构”,但无论如何先记录下来吧~
使用了额外的存储空间。。。
class Different {
public:
bool checkDifferent(string iniString) {
// write code here
int A[256] = {0};
for(int i = 0; i < iniString.size(); i++) {
if(A[iniString[i]] == 0)
A[iniString[i]]++;
else if(A[iniString[i]] == 1)
return false;
}
return true;
}
};
Solution2:
参考网址:https://www.nowcoder.com/profile/6664749/codeBookDetail?submissionId=16328058
看到多数人的答案,我觉得似乎有些不妥。
1)哈希法 首先char类型判断重复,用hash数组最方便,只需要256个bool类型即可,O(n)的时间(其实只要判断前257个就行了O(1),抽屉原理),但是题目要求不能使用额外的存储结构,那么这个方法KO掉。
2)遍历 那么只能用两层for循环遍历,时间复杂度为O(n*n),但是根据抽屉原理,没必要遍历到N,只需要遍历到前257就够了,如果N<257就遍历到N,所以时间复杂度其实为O(1)!!!
3)排序 既然题目要求不能使用额外空间,而参数列表没有const或引用,那么就可以对字符串排序,然后再判断,需要O(nlogn)排序,然后再遍历一遍O(n)。其实也没必要全都排序,只需前257个,同抽屉原理。
4)Partition 基于快速排序的partition,可以边排序边找重复 ,也即是每次partition之后,判断中间key元素与两边元素是否相同,相同则返回false,不同再进行下一轮partition.时间复杂度也是O(nlongn),但要比排序速度快。
综上,其实此题若改为长度为N的整形数组,不用额外空间 ,这题目就Perfect!下面贴出基于partition的代码。
class Different {
bool quick_check(string &str,int low,int high){
int first = low,last = high;
char key = str[first];
if (low>=high)
return true;
while(first<last){
while(first <last && str[last] >= key)
last--;
str[first] = str[last];
while(first<last && str[first] <= key)
first++;
str[last] = str[first];
}
str[first] = key;
if (first>low && str[first] == str[first-1])
return false;
if (first<high && str[first] == str[first+1])
return false;
return quick_check(str,low,first-1) && quick_check(str,first+1,high);
}
public:
bool checkDifferent(string iniString) {
// write code here
return quick_check(iniString,0,iniString.size()-1);
}
};
5)正则表达式 正则表达式的功能真是很强大,是处理字符串的利器。除了不太容易学之外没什么缺点了。。
这里贴一个java版的正则表达式的代码
public boolean checkDifferent(String iniString) {
return !iniString.matches(".*(.)(.*\\1).*");
}
.:代表任意一个字符
.:代表任意一个字符后面有0个或多个字符
(.):选择字符中任意一个字符进行复制 和后面的(.\1)结合进行判断是否后面存在一个字符与它相同
(.)(.\1):匹配案例 aa(即首尾相同的abcsa)
(.)(.\1).:匹配案例 aa
.(.)(.\1):匹配案例 aa
.(.)(.\1).:匹配案例 aa