谁能解释这段代码是如何工作的?

Posted

技术标签:

【中文标题】谁能解释这段代码是如何工作的?【英文标题】:Can anyone explain how this block of code work? 【发布时间】:2018-12-24 05:34:11 【问题描述】:

我试图理解这段代码,它检查 2 个不同字符串的字谜。

int[] charSet = new int[256];

    for (int i = 0; i < sA.length(); i++) 
        charSet[sA.charAt(i)]++;
    
    for (int i = 0; i < sB.length(); i++) 
        charSet[sB.charAt(i)]--;
    

    int deletion = 0;
    for (int i = 0; i < 256; i++) 
        deletion += Math.abs(charSet[i]);
    

    System.out.println("The amount of deletion needed: " + deletion);

我使用调试来真正掌握将 char 索引放置在数组中的想法,但是当我检查数组的内容时,要么是 0,要么是 1。但是sA.charat(i) 不是返回的字符串的索引不是 0 或 1 吗?

那么charSet[sA.charAt(i)]++; 这个代码到底做了什么,据我了解,它获取字符串的 char 索引并添加到​​数组中,但 ++ 的意义何在?

另外,更具体地说,deletion += Math.abs(charSet[i]); 这行代码是如何工作的,因为它所做的只是将一个数组的相应索引添加到另一个数组之上。但我真的不明白如何检查 2 个字符串的字谜。

如果有人能详细解释一下,我将不胜感激。

【问题讨论】:

否,String.charAt(i) 在字符位置 i 返回字符 “但是sA.charat(i) 不是返回字符串的索引” 不,charAt 在给定索引处返回charchar 可能是一个字母 (A-Z),然后 ASCII 值 (65-90) 是 charSet 数组的索引。 【参考方案1】:

您似乎误解了charSet[sA.charAt(i)]++; 的目的和行为。一旦你明白为什么会有那条线,其他一切就变得简单了。

charSet 这里计算第一个字符串有多少个字符。例如,如果字符串是aab,那么charSet 的索引97 将是2,索引98 将是1,其余的都是0。 “a”的 int 值为 97,“b”的 int 值为 98。

第一个 for 循环遍历第一个字符串的每个字符。 charSet[sA.charAt(i)]++; 基本上将该字符的计数加 1。对于字符串 aab,表达式的计算结果为:

// note that charAt(i) returns the character at index i of the string
charSet[97]++; // 1st iteration
charSet[97]++; // 2nd iteration
charSet[98]++; // 3rd iteration

现在第二个 for 循环与第二个字符串相反。这一次,我们倒计时。为什么?因为如果这两个字符串是字谜,那么在对字符进行计数和对相同的字符进行计数之后,我们最终会得到用 0 填充的 charSet

假设这两个字符串不是字谜。这意味着在前两个 for 循环之后,charSet 包含一些非 0。我们将这些非 0 的绝对值相加,以获得需要添加/删除多少个字符才能使两个字符串变位词。


请注意,如果字符串包含值超过 256 的字符,此程序将崩溃!解决此问题的更好方法是使用HashMap 来计算字符数。

【讨论】:

看完上面的解释+这个,我真的明白了。感谢您的详细解释。 256 表示该程序仅限于 C0 Controls 和 Basic Latin 以及 C1 Controls 和 Latin-1 Supplement Unicode blocks。 ?【参考方案2】:

字谜是可以通过重新排列另一个单词的字母来形成的单词或短语。例如pale -&gt; leap。这两个词使用相同的一组字母,即l, a, p, e

您共享的代码遵循一个逻辑,它初始化一个长度为 256 的空整数数组以包括所有小写、大写、特殊字符等。

它首先遍历第一个字符串中的每个字母,并增加整数数组中字母的 ascii 值的计数。

然后它遍历第二个字符串中的每个字母,并减少整数数组中字母的 ascii 值的计数。

这背后的逻辑是,如果两个字符串都是字谜,这意味着它们使用相同的字符集。如果是这种情况,那么在两次迭代之后,int 数组中每个元素的值仍将保持为零。如果任何值大于或小于零,则表示两个字符串中使用的字母存在差异,因此它们不是字谜。

【讨论】:

【参考方案3】:
public static int getDeletion(String sA, String sB) 
    //this creates an array with 256 items, so that is an item for all the characters.
    int[] charSet = new int[256];

    //This goes through each letter of sA, and it increments the value at the value of the current letter in ASCII
    //So if the first letter is A , it will increment the 65th item of charSet, because 65 is the ASCII value of a.
    //It does this for all letters of sA.
    for (int i = 0; i < sA.length(); i++) 
        charSet[sA.charAt(i)]++;
    

    //It does the same here for sB, but it subtracts the value.
    for (int i = 0; i < sB.length(); i++) 
        charSet[sB.charAt(i)]--;
    

    //now we have at each item of charSet the amount of difference between the two strings for each letter.
    //So if sA has 2 As and sB has 1 A, item 65 of charSet will be 1.
    //If sA has 1 A and sB has 2 As, item 65 of charSet will be -1.

    int deletion = 0;
    for (int i = 0; i < 256; i++) 
        //Here we add the amount of difference from each character to the 'deletion' variable. This will give us a total difference score.
        //The Math.abs() makes sure the item is positive (so -5 will become 5).
        deletion += Math.abs(charSet[i]);
    
    return deletion;

    //So say we compare "adc" and "bca". After the 2nd for loop, each item of charSet is 0, except value 98 and 100 
    //(ASCII value for b and c respectively).
    //value 98 will be -1, because sB has 1 more b than sA
    //value 100 will be 1, because sA has 1 more d than sB
    //The -1 will be converted to a 1, because of the Math.abs()
    //So in the for loop every value is added up to become 2, which is returned.

【讨论】:

非常感谢这篇详细的评论,我现在完全掌握了它的作品。谢谢。【参考方案4】:

charSet 表示 char 原始类型的 256 个不同的可能值。 正如 biziclop 和 Andreas 在 cmets 中所指出的,还有更多。

这两个字符串,本质上是字符数组,被迭代。 charSet 数组基本上记录了字符串中每个字符的出现次数。 对于第一个字符串,每次出现计数增加一,对于第二个,计数减少一。因此,如果字符串是彼此的字谜,则 charSet 数组中的每个 int 都应为 0。

最后,charSet 数组被迭代以总结字符串之间缺失的字符。您可以将删除变量视为字符串之间差异的度量。

【讨论】:

char 原始类型有超过 256 个可能的值。只是这个程序只处理前 256 个字符,因此如果遇到超出该范围的字符就会失败。 “Java 中的 char 原始类型有 256 个可能的值” 错误。 char 是 UTF-16 编码的 2 字节 Unicode 字符值,因此它有超过 60000 个值(并非所有 65536 个值都有效) 是的,我忘记了。会改的。 @Andreas 我们以完全相同的顺序制作了完全相同的 cmets :)

以上是关于谁能解释这段代码是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

谁能解释这段代码到底做了啥?

谁能解释为啥这段代码不起作用?

使用 xml 将 csv 值转换为表行。谁能解释一下下面提到的查询将如何工作

谁能向我解释这段代码?

谁能解释一下这个java代码是如何工作的?

这段代码是如何工作的?