leetcode常规算法题复盘(第八期)——重构字符串

题目原文

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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原文地址:https://www.cnblogs.com/monkiki/p/14066267.html