使第一个字符串成为第二个字符串的 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)) 中运行的非常简单的方法如下:
让我们将两个子字符串称为strA
和strB
以进行下面的讨论。对于每个子字符串:将字符串中的字符映射到一个数组,该数组保存字符串中特定字符的出现次数。例如,如果假设字符串中只有非大写字母,则将每个字符的 ASCII 值映射到大小为 26(英文字母)的整数数组的条目,将 ASCII 值移动 -96 以获得映射 ASCII (a...z) -> 索引(0...25)。在接下来的讨论中,我们将这些“出现次数”数组称为a
和b
,分别对应于子字符串strA
和strB
。
此后,对于每个索引i
(在 0...25 中),其中a[i] * b[i] > 0
,值min(a[i], b[i])
向我们显示了a
和b
中与索引关联的字符的符合顺序i.
合规顺序的总和给出了子字符串strA
和strB
之间的总合规,如果这个总和等于这些子字符串的长度(它们的长度相等,或者返回是-1
),那么这两个子串 strA
和 strB
是彼此的字谜。
下面的例子展示了这个在 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?的主要内容,如果未能解决你的问题,请参考以下文章