每日一题--移除字符串中重复的字符(Cracking the Coding Interview)

题目

  • 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_39860046/article/details/87736877