示例:给定一个字符串(在本示例中为char *word
),您想查找重复的字符(字节)。
我想知道是否有人可以向我解释以下工作原理:
int table[256] = {0};
for (int i = 0; i < len; i++) table[word[i]]++;
之后,您可以检查另一个循环是否重复:
for (int i = 0; i < len; i++) if (table[word[i]] > 1) { … }
这是如何工作的?我不明白为什么表中重复的字符> 1?
答案 0 :(得分:2)
将我的评论转换为半连贯答案。
第一个循环计算每个字节值在0..255范围内的出现次数(对于找到的每个字节值,它在字节计数中增加一个);重新扫描会在字符串中找到一个以上出现的字节值-重复项的定义。
循环都假定字符串是用单字节代码集而不是像UTF-8这样的多字节代码集编码的。他们还假定纯char
是无符号类型(不常见;大多数x86平台具有带符号纯char
类型),或者字符串中没有任何值,其中word[i]
为负(无重音字符)。
因此,出于安全考虑,代码应为:
for (int i = 0; i < len; i++)
table[(unsigned char)word[i]]++;
for (int i = 0; i < len; i++)
{
if (table[(unsigned char)word[i]] > 1)
{
…
}
}
您可以使用word[i] & 0xFF
代替演员表;它甚至具有更少的字符,但我认为演员表更清晰(字符数是红色鲱鱼,请不要追逐它)。请注意,无论普通char
是带符号类型还是无符号类型,这两种变体(广播和掩码)都可以正常工作(尽管代码确实做出了CHAR_BIT
为8而不是较大的数字-不能较小。)
但是为什么将它添加到找到的每个char值中,而不仅仅是添加到表中当前位置的那个char值中?当我打印出内存位置时,我从示例字符串
"abcda"
中看到,两个a在内存中是相同的。我认为在表数组中它们必须位于不同(但连续)的位置;为什么一样?
当您在字符串中找到'a'
时,会有一个与该字符关联的字节值,通常为97。因此,当计数代码读取word[i]
且word[i]
的内容为'a'
时,就好像数组中有97个(实际上,数组中有97个),因此第一个循环递增table[97]
-在读取a
中的第一个abcda
时将其从0更改为1,而在读取第二个a
时将其从1更改为2。 >
在说完所有内容后,字符只是数字(但是在说完所有内容之前,可能有很多话要说;很多情况下,您不必经历所有这些事情)时间)。
答案 1 :(得分:0)
function removeDuplicates(str) {
let result = "";
let freq = {};
for (let i = 0; i < str.length; i++) {
let char = str[i];
let smallChar = char.toLowerCase();
let bigChar = char.toUpperCase();
if (freq[smallChar]) {
freq[char]++;
} else if (freq[bigChar]) {
freq[char]++;
} else {
freq[char] = 1;
result = result + char;
}
}
console.log(result);
}
removeDuplicates("ItWorks with any word");