1.3 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.
DeleteDuplicate1()函数使用的是递归的方法,当处理到size大小的时候,假设前size-1的字符串已经消除了重复数据(多余的数据替换成了'\0');如果前size-1的字符串中有字符与size处字符相同,则把size处字符替换为'\0';全部处理完后,删除'\0'。这个是最开始想到的方法,觉得有两个问题:1. 使用了系统堆栈O(n),不知道算不算是additional buffer;2. 最后删除'\0'的步骤感觉很多余,不过递归过程肯定不能移动字符串,否则在循环中能处理掉重复数据就好了。在判断字符串时候为空的时候用了str == null,导致空字符串输入时出错。。。
DeleteDuplicate2()函数使用了hash,不过256的数组应该算是additional buffer了吧。
DeleteDuplicate3()函数参照了书中的解法,把整个字符串分成两部分,前面一部分(tail变量之前的字符串)为已经处理过没有重复数据的字符串,后面的字符串为待处理字符串。i,j变量分别用来遍历这两部分字符串。本质上跟递归版本类似,但没想到这里tail变量的作用。
Test Cases书上写了6个,漏掉了2个,思维还不严密:1. String does not contain any duplicates, e.g.: abcd; 2. String contains all duplicates, e.g.: aaaa; 3. Null string; 4. Empty string; 5. String with all continuous duplicates, e.g.: aaabbb; 6. String with non-contiguous duplicates, e.g.: abababa
package Question1_3;
public class Question1_3
{
public static void main(String[] args)
{
Question1_3 q = new Question1_3();
StringBuffer[] strings =
{
new StringBuffer("abcdefg"),
new StringBuffer("aabbccddeeffgghhiijjkkllmmnn"),
new StringBuffer("abcdefgabcdefg"),
new StringBuffer("aaaaaaa"),
new StringBuffer("t"),
new StringBuffer("ababababababa"),
new StringBuffer("12 32 9 ' e.g e' f"),
new StringBuffer(),
};
for (StringBuffer str : strings)
{
q.DeleteDuplicate1(str);
System.out.println(str);
}
}
public void DeleteDuplicate1(StringBuffer str)
{
// can not use str == null to check whether str is empty
if (str.length() == 0)
return;
DeleteDuplicate1Helper(str, str.length());
// delete markers
int index;
while ((index = str.indexOf("\0")) != -1)
{
str.deleteCharAt(index);
}
}
private void DeleteDuplicate1Helper(StringBuffer str, int size)
{
if (size == 1)
return;
else
{
// recursively solve the problem until size == 1
DeleteDuplicate1Helper(str, size - 1);
// for every char before str[size-1], check if they are equal. If so, then
// mark str[size-1] as duplicated.(change it to '\0')
for (int i = 0; i < size-1; i++)
if (str.charAt(i) == str.charAt(size - 1))
{
str.setCharAt(size - 1, '\0');
break;
}
}
}
public void DeleteDuplicate2(StringBuffer str)
{
if (str.length() == 0 || str.length() == 1)
return;
boolean[] chars = new boolean[256];
int i, tail = 0;
for (i = 0; i < str.length(); i++)
{
// there is no duplicate at i, so add str[i] to tail.(copy and increment)
if (chars[str.charAt(i)] == false)
{
chars[str.charAt(i)] = true;
str.setCharAt(tail, str.charAt(i));
tail++;
}
}
str.delete(tail, str.length());
}
public void DeleteDuplicate3(StringBuffer str)
{
if (str.length() == 0 || str.length() == 1)
return;
int i, j, tail = 1;
for (i = 1; i < str.length(); i++)
{
// check if there is duplicate
for (j = 0; j < tail; j++)
if (str.charAt(i) == str.charAt(j))
break;
// there is no duplicate
if (j == tail)
{
str.setCharAt(tail, str.charAt(i));
tail++;
}
}
str.delete(tail, str.length());
}
}