使第一个字符串成为第二个字符串的 Anagram?

Posted

技术标签:

【中文标题】使第一个字符串成为第二个字符串的 Anagram?【英文标题】:Make first string the Anagram of the second string? 【发布时间】:2016-03-29 14:05:20 【问题描述】:

每个测试用例将包含一个长度为 len(S1)+len(S2) 的字符串,这将是两个字符串的串联。给定的字符串将仅包含从 a 到 z 的字符。

任务

找出第一个字符串最少字符数(这将是给定字符串的前半部分)更改为使其成为第二个字符串的变位词。(这将是给定字符串的后半部分)。

输入: aaabbb 输出:3 因为需要将 3 a(s) 替换为 3 b(s) 才能使 string1(aaa) 成为 string2(bbb) 的字谜

我的方法:

如果字符串长度不是偶数..那么前半部分不能是后半部分的字谜...那么print -1

否则:

    我计算每个字母表的字符数并将其存储为一个包含 26 个元素的数组。表示从 a-z 开始的每个字母表的重复次数。

    我为 2 个字符串创建了 2 个这样的数组。

3.我检查两个数组以打印需要更改的字符数。由于我需要将第一个字符串作为第二个字符串的字谜。我将检查两个数组。

Firststring[i] > SecondString[i] ...递增计数!

这种方法需要 o(n^2) 时间。 (遍历每个字符串并为每个字符串形成数组)。

我需要一个更好的解决方案!

【问题讨论】:

提示:如果对单词的字母进行排序会发生什么? 使用地图而不是数组来存储每个字母的重复? @JonSkeet ... 排序一个单词然后? 不,只是使用一个字符串...例如将“apple”映射到“aelpp”。考虑一下对互为字谜的单词这样做的结果。当然,这只有助于“检查两个单词是否是字谜”——而不是更大的任务。我不太关注更大的任务,部分原因是你没有给出任何例子。 嗯好吧!但是排序并没有给出优化的解决方案? 【参考方案1】:

在线性时间 (O(n)) 中运行的非常简单的方法如下:

让我们将两个子字符串称为strAstrB 以进行下面的讨论。对于每个子字符串:将字符串中的字符映射到一个数组,该数组保存字符串中特定字符的出现次数。例如,如果假设字符串中只有非大写字母,则将每个字符的 ASCII 值映射到大小为 26(英文字母)的整数数组的条目,将 ASCII 值移动 -96 以获得映射 ASCII (a...z) -> 索引(0...25)。在接下来的讨论中,我们将这些“出现次数”数组称为ab,分别对应于子字符串strAstrB。 此后,对于每个索引i(在 0...25 中),其中a[i] * b[i] > 0,值min(a[i], b[i]) 向我们显示了ab 中与索引关联的字符的符合顺序i. 合规顺序的总和给出了子字符串strAstrB 之间的总合规,如果这个总和等于这些子字符串的长度(它们的长度相等,或者返回是-1 ),那么这两个子串 strAstrB 是彼此的字谜。

下面的例子展示了这个在 Swift 中的实现,但是我使用了一种纯粹的命令式方法,所以它应该很容易被翻译成你选择的最喜欢的编程语言。

let myString = "aaabbb"
var myOutput: Int?
let numChars = myString.characters.count

if numChars%2 == 0 

    let midIndex = myString.startIndex.advancedBy(numChars/2)
    let myLeftString = myString.substringToIndex(midIndex)
    let myRightString = myString.substringFromIndex(midIndex)

    let numDifferentLetters = 26 // asymptotic behaviour: assume n > numDifferentLetters
    var letterOccurencesLhs = [Int](count: numDifferentLetters, repeatedValue: 0) // < n
    var letterOccurencesRhs = letterOccurencesLhs // swift: arr value type, < n

    // n/2
    for charAscii in myLeftString.utf8 
        letterOccurencesLhs[Int(charAscii)-96] += 1
    

    // n/2
    for charAscii in myRightString.utf8 
        letterOccurencesRhs[Int(charAscii)-96] += 1
    

    // check order of compliance for each letter, w.r.t. numDiffLetters, < n
    var mySum = 0
    for i in 0 ..< numDifferentLetters 
        if letterOccurencesLhs[i] * letterOccurencesRhs[i] > 0 
            mySum += min(letterOccurencesLhs[i], letterOccurencesRhs[i])
        
    

    myOutput = numChars/2-mySum


else 
    myOutput = -1


print("Output: \(myOutput!)") // 3 for "aaabbb"
                              // 2 for "aaabbbbbbbab"

    // Complexity: O(n)

【讨论】:

以上是关于使第一个字符串成为第二个字符串的 Anagram?的主要内容,如果未能解决你的问题,请参考以下文章

Perl:组合两个哈希数组的值并使第二个数组的值成为输出哈希的键

Java找到StringBuffer中字符之间的区别

循环 函数 数组

浅析parseInt与parseFloat的区别

使用哈希比较 Anagram 的两个字符串 [关闭]

使第三个可见行成为唯一可选择的行