题目原文
767. 重构字符串
给定一个字符串S
,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = "aab" 输出: "aba"
示例 2:
输入: S = "aaab" 输出: ""
注意:
S
只包含小写字母并且长度在[1, 500]
区间内。
标准题解
最大堆:
1 class Solution: 2 def reorganizeString(self, S: str) -> str: 3 if len(S) < 2: 4 return S 5 6 length = len(S) 7 counts = collections.Counter(S) 8 maxCount = max(counts.items(), key=lambda x: x[1])[1] 9 if maxCount > (length + 1) // 2: 10 return "" 11 12 queue = [(-x[1], x[0]) for x in counts.items()] 13 heapq.heapify(queue) 14 ans = list() 15 16 while len(queue) > 1: 17 _, letter1 = heapq.heappop(queue) 18 _, letter2 = heapq.heappop(queue) 19 ans.extend([letter1, letter2]) 20 counts[letter1] -= 1 21 counts[letter2] -= 1 22 if counts[letter1] > 0: 23 heapq.heappush(queue, (-counts[letter1], letter1)) 24 if counts[letter2] > 0: 25 heapq.heappush(queue, (-counts[letter2], letter2)) 26 27 if queue: 28 ans.append(queue[0][1]) 29 30 return "".join(ans) 31 32 33 #作者:LeetCode-Solution 34 #链接:https://leetcode-cn.com/problems/reorganize-string/solution/zhong-gou-zi-fu-chuan-by-leetcode-solution/ 35 #来源:力扣(LeetCode) 36 #著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
复杂度分析
时间复杂度:O(nlog∣Σ∣+∣Σ∣)O(nlog|Sigma| + |Sigma|)O(nlog∣Σ∣+∣Σ∣),其中 nnn 是字符串的长度,ΣSigmaΣ 是字符集,在本题中字符集为所有小写字母,∣Σ∣=26|Sigma|=26∣Σ∣=26。
遍历字符串并统计每个字母的出现次数,时间复杂度是 O(n)O(n)O(n)。
将每个字母加入最大堆,字母个数最多为 ∣Σ∣|Sigma|∣Σ∣,这里设真正出现的小写字母数量为 ∣Σ′∣|Sigma'|∣Σ′∣,那么时间复杂度是 O(∣Σ∣)O(|Sigma|)O(∣Σ∣) 加上 O(∣Σ′∣log∣Σ′∣)O(|Sigma'|log|Sigma'|)O(∣Σ′∣log∣Σ′∣) 或 O(∣Σ′∣)O(|Sigma'|)O(∣Σ′∣)。前者是对数组进行遍历的时间复杂度 O(∣Σ∣)O(|Sigma|)O(∣Σ∣),而后者取决于是将每个字母依次加入最大堆,时间复杂度为 O(∣Σ′∣log∣Σ′∣)O(|Sigma'|log|Sigma'|)O(∣Σ′∣log∣Σ′∣);还是直接使用一次堆的初始化操作,时间复杂度为 O(∣Σ′∣)O(|Sigma'|)O(∣Σ′∣)。
重构字符串需要对最大堆进行取出元素和添加元素的操作,取出元素和添加元素的次数都不会超过 nnn 次,每次操作的时间复杂度是 O(log∣Σ′∣)O(log|Sigma'|)O(log∣Σ′∣),因此总时间复杂度是 O(nlog∣Σ′∣)O(nlog|Sigma'|)O(nlog∣Σ′∣)。由于真正出现的小写字母数量为 ∣Σ′∣|Sigma'|∣Σ′∣ 一定小于等于字符串的长度 nnn,因此上面的时间复杂度中 O(n)O(n)O(n),O(∣Σ′∣log∣Σ′∣)O(|Sigma'|log|Sigma'|)O(∣Σ′∣log∣Σ′∣) 和 O(∣Σ′∣)O(|Sigma'|)O(∣Σ′∣) 在渐进意义下均小于 O(nlog∣Σ′∣)O(nlog|Sigma'|)O(nlog∣Σ′∣),只需要保留 O(∣Σ∣)O(|Sigma|)O(∣Σ∣)。由于 ∣Σ′∣≤∣Σ∣|Sigma'| leq |Sigma|∣Σ′∣≤∣Σ∣,为了不引入额外符号,可以将时间复杂度 O(nlog∣Σ′∣)O(nlog|Sigma'|)O(nlog∣Σ′∣) 写成 O(nlog∣Σ∣)O(nlog|Sigma|)O(nlog∣Σ∣)。
总时间复杂度是 O(nlog∣Σ∣+∣Σ∣)O(nlog|Sigma| + |Sigma|)O(nlog∣Σ∣+∣Σ∣)。
空间复杂度:O(∣Σ∣)O(|Sigma|)O(∣Σ∣),其中 ΣSigmaΣ 是字符集,在本题中字符集为所有小写字母,∣Σ∣=26|Sigma|=26∣Σ∣=26。这里不计算存储最终答案字符串需要的空间(以及由于语言特性,在构造字符串时需要的额外缓存空间),空间复杂度主要取决于统计每个字母出现次数的数组和优先队列。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reorganize-string/solution/zhong-gou-zi-fu-chuan-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
计数
1 class Solution: 2 def reorganizeString(self, S: str) -> str: 3 if len(S) < 2: 4 return S 5 6 length = len(S) 7 counts = collections.Counter(S) 8 maxCount = max(counts.items(), key=lambda x: x[1])[1] 9 if maxCount > (length + 1) // 2: 10 return "" 11 12 reorganizeArray = [""] * length 13 evenIndex, oddIndex = 0, 1 14 halfLength = length // 2 15 16 for c, count in counts.items(): 17 while count > 0 and count <= halfLength and oddIndex < length: 18 reorganizeArray[oddIndex] = c 19 count -= 1 20 oddIndex += 2 21 while count > 0: 22 reorganizeArray[evenIndex] = c 23 count -= 1 24 evenIndex += 2 25 26 return "".join(reorganizeArray) 27 28 29 #作者:LeetCode-Solution 30 #链接:https://leetcode-cn.com/problems/reorganize-string/solution/zhong-gou-zi-fu-chuan-by-leetcode-solution/ 31 #来源:力扣(LeetCode) 32 #著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
复杂度分析
时间复杂度:O(n+∣Σ∣)O(n+|Sigma|)O(n+∣Σ∣),其中 nnn 是字符串的长度,ΣSigmaΣ 是字符集,在本题中字符集为所有小写字母,∣Σ∣=26|Sigma|=26∣Σ∣=26。
遍历字符串并统计每个字母的出现次数,时间复杂度是 O(n)O(n)O(n)。
重构字符串需要进行 nnn 次放置字母的操作,并遍历每个字母得到出现次数,时间复杂度是 O(n+∣Σ∣)O(n+|Sigma|)O(n+∣Σ∣)。
总时间复杂度是 O(n+∣Σ∣)O(n+|Sigma|)O(n+∣Σ∣)。
空间复杂度:O(∣Σ∣)O(|Sigma|)O(∣Σ∣),其中 nnn 是字符串的长度,ΣSigmaΣ 是字符集,在本题中字符集为所有小写字母,∣Σ∣=26|Sigma|=26∣Σ∣=26。这里不计算存储最终答案字符串需要的空间(以及由于语言特性,在构造字符串时需要的额外缓存空间),空间复杂度主要取决于统计每个字母出现次数的数组和优先队列。空间复杂度主要取决于统计每个字母出现次数的数组。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reorganize-string/solution/zhong-gou-zi-fu-chuan-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。