题目
- Design an algorithm and write code to remove the duplicate characters in a string without using any additional buffer. NOTE: One or two additional variables are fine. An extra copy of the array is not.
FOLLOW UP,
Write the test cases for this method. - 设计算法并写出代码移除字符串中重复的字符,不能使用额外的缓存空间。注意: 可以使用额外的一个或两个变量,但不允许额外再开一个数组拷贝。
进一步地,
为你的程序写测试用例。
思路
- 要将字符数组中重复的字符就地(in place)移除,在前天的题目中我们已经做过找重复字符。在此题中,明确给出要求不允许额外再开一个数组,此时要向面试官问清楚, 这里是指不允许再开任何一个数组,还是说可以开一个固定大小(与字符串长度无关)的数组。
- 如果不允许再开任何一个数组,只能用额外的一到两个变量,可以依次访问 这个数组中的字符,每访问一个,就将从该字符到结尾的所有字符中与该字符相同的元素去掉。不过这样做比较慢,时间复杂度为O(n^2 ),代码见removeDuplicate1()。
- 如果可以开一个固定大小(与字符串长度无关)的数组,那么我们便可以用到前天找重复字符的方法,这里仅使用其中位运算的方法,代码见removeDuplicate2(),时间复杂度为O(n)。
代码
#include<iostream>
#include<cstring>
using namespace std;
void removeDuplicate1(string &s) {
int n = s.length();
if(n < 2) return;
int p = 0;
for (int i = 0; i < n; i++) {
if(s[i] != '\0') {
s[p++] = s[i];
for (int j = i+1; j < n; j++) {
if(s[i] == s[j]) s[j] = '\0';
}
}
}
s = s.substr(0,p);
//s[p] = '\0';
}
void removeDuplicate2(string &s) {
int n = s.length();
if(n < 2) return;
int a[8];
int p = 0;
memset(a, 0, sizeof(a));
for (int i = 0; i < n; i++) {
int d = (int)s[i];
int index = d / 32;
int shift = d % 32;
if(!(a[index] & 1 << shift)) {
a[index] |= 1 << shift;
s[p++] = s[i];
}
}
s = s.substr(0,p);
}
int main() {
string s1 = "abccdcdcde";
string s2 = "abcdefabfgkad";
string s3 = "";
string s4 = "aaaaaaaa";
string s5 = "abababababaABAB";
string s6 = " ";
string s7 = "ccccccdddd";
removeDuplicate1(s1);
removeDuplicate2(s2);
removeDuplicate2(s3);
removeDuplicate2(s4);
removeDuplicate2(s5);
removeDuplicate1(s6);
removeDuplicate1(s7);
cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl<<s5<<endl<<s6<<endl<<s7<<endl;
return 0;
}