String 在O(n)时间内,使用恒定空间,即不使用额外的辅助数组,查找给定字符串中的非唯一字符
给定仅包含小写字母a-z的字符串s,查找(即打印)重复的字符 对于ex,如果字符串s=aabcacdddec 输出:a c d 解决这一问题的方法有三种: [brute force]检查字符串的每个字符,即s[i]与其他每个字符,如果两者相同,则打印 时间复杂度:在^2上 空间复杂度:O1 [排序,然后比较相邻元素]在logn time上排序后,遍历字符串并检查s[i]和s[i+1]是否相等 时间复杂度:On logn+On=On logn 空间复杂度:O1 [将字符计数存储在数组中]创建一个大小为26的数组,以跟踪a-z,并且对于数组中的每个s[i],增量值存储在索引=s[i]-26处。最后遍历数组并打印所有元素,即值大于1的“a”+i 时间复杂性:On 空间复杂度:O1,但我们有一个单独的数组来存储每个元素的频率 是否有不使用任何数组/哈希表/映射等的On方法 提示:使用位向量这是最简单的,所以一般来说-没有额外的空间,没有办法在On中解决它 但是,如果您将字母表视为常量大小,则a-z字符是非常常量的,您可以在O1空间中创建这些字符的位集[它是常量!],或者检查On中的每个字符,如果它重复多次,则它将是O常量*n,它仍处于On状态 第一个解决方案的伪代码:String 在O(n)时间内,使用恒定空间,即不使用额外的辅助数组,查找给定字符串中的非唯一字符,string,algorithm,String,Algorithm,给定仅包含小写字母a-z的字符串s,查找(即打印)重复的字符 对于ex,如果字符串s=aabcacdddec 输出:a c d 解决这一问题的方法有三种: [brute force]检查字符串的每个字符,即s[i]与其他每个字符,如果两者相同,则打印 时间复杂度:在^2上 空间复杂度:O1 [排序,然后比较相邻元素]在logn time上排序后,遍历字符串并检查s[i]和s[i+1]是否相等 时间复杂度:On logn+On=On logn 空间复杂度:O1 [将字符计数存储在数组中]创建一个大
bit seen[] = new bit[SIZE_OF_ALPHABET] //contant!
bit printed[] = new bit[SIZE_OF_ALPHABET] //so is this!
for each i in seen.length: //init:
seen[i] = 0
printed[i] = 0
for each character c in string: //traverse the string:
i = intValue(c)
//already seen it and didn't print it? print it now!
if seen[i] == 1 and printed[i] == 0:
print c
printed[i] = 1
else:
seen[i] = 1
for each character c from a-z: //constant number of repeats is O(1)
count = 0
for each character x in the string: //O(n)
if x==c:
count += 1
if count > 1
print count
第二种解决方案的伪代码:
bit seen[] = new bit[SIZE_OF_ALPHABET] //contant!
bit printed[] = new bit[SIZE_OF_ALPHABET] //so is this!
for each i in seen.length: //init:
seen[i] = 0
printed[i] = 0
for each character c in string: //traverse the string:
i = intValue(c)
//already seen it and didn't print it? print it now!
if seen[i] == 1 and printed[i] == 0:
print c
printed[i] = 1
else:
seen[i] = 1
for each character c from a-z: //constant number of repeats is O(1)
count = 0
for each character x in the string: //O(n)
if x==c:
count += 1
if count > 1
print count
字符集的大小是一个常量,因此可以扫描输入26次。您只需要一个计数器来存储您看到与当前迭代对应的角色的次数。在每次迭代结束时,如果计数器大于1,则打印该字符 它在运行时打开,在辅助空间中打开O1。在Java中实现
public static void findDuplicate(String str) {
int checker = 0;
char c = 'a';
for (int i = 0; i < str.length(); ++i) {
int val = str.charAt(i) - c;
if ((checker & (1 << val)) > 0) {
System.out.println((char)(c+val));
}else{
checker |= (1 << val);
}
}
}
使用as int作为存储,并执行逐位运算符查找重复项
它在……上。。解释如下
输入为abddc
i==0
STEP #1 : val = 98 - 98 (0) str.charAt(0) is a and conversion char to int is 98 ( ascii of 'a')
STEP #2 : 1 << val equal to ( 1 << 0 ) equal to 1 finally 1 & 0 is 0
STEP #3 : checker = 0 | ( 1 << 0) equal to 0 | 1 equal to 1 checker is 1
i==1
STEP #1 : val = 99 - 98 (1) str.charAt(1) is b and conversion char to int is 99 ( ascii of 'b')
STEP #2 : 1 << val equal to ( 1 << 1 ) equal to 2 finally 1 & 2 is 0
STEP #3 : checker = 2 | ( 1 << 1) equal to 2 | 1 equal to 2 finally checker is 2
i==2
STEP #1 : val = 101 - 98 (3) str.charAt(2) is d and conversion char to int is 101 ( ascii of 'd')
STEP #2 : 1 << val equal to ( 1 << 3 ) equal to 8 finally 2 & 8 is 0
STEP #3 : checker = 2 | ( 1 << 3) equal to 2 | 8 equal to 8 checker is 8
i==3
STEP #1 : val = 101 - 98 (3) str.charAt(3) is d and conversion char to int is 101 ( ascii of 'd')
STEP #2 : 1 << val equal to ( 1 << 3 ) equal to 8 finally 8 & 8 is 8
Now print 'd' since the value > 0
您也可以使用位向量,这取决于它将节省空间的语言。在java中,我更愿意在C递归解决方案中使用int来实现这个固定的26常量大小写
static void getNonUniqueElements(string s, string nonUnique)
{
if (s.Count() > 0)
{
char ch = s[0];
s = s.Substring(1);
if (s.LastIndexOf(ch) > 0)
{
if (nonUnique.LastIndexOf(ch) < 0)
nonUnique += ch;
}
getNonUniqueElements(s, nonUnique);
}
else
{
Console.WriteLine(nonUnique);
return;
}
}
static void Main(string[] args)
{
getNonUniqueElements("aabcacdddec", "");
Console.ReadKey();
}
使用位集意味着您可以在一次过程中完成此操作,甚至比我的答案更好。常量空格并不意味着没有空格。该数组将具有恒定大小的26个元素。