土豆炒青椒
土豆炒青椒

认真刷 767 ~ 识别字符串

刷题贵在坚持,持之以恒,水滴石穿~

基本信息

  • 题号:767
  • 题厂:特斯拉
  • 难度系数:中



已知一个字符串,重新安插字符,要求相同字符不能连在一起,返回该字符。如果满足不了条件,就返回空……

例如:s = "aab",返回 "aba";s = "aaab",返回 "",因为没有满足的情况


解题思路

  • 为了尽可能满足相同字符不挨在一起,于是考虑从出现频率高的字符开始排
  • 为了让相邻字符不相同,于是问题转换为——如何有效间隔安插。间隔安插问题与 #621 安排任务 似曾相识。在 #621 安排任务 一题我们引入 heap 解决问题,所以本题一样可以引入 heap 帮忙解决问题……

class Solution:
    def reorganizeString(self, s: str) -> str:
        # Counter 捷径:统计字符串各字符出现频率并转化为 hashmap 格式
        count = Counter(s)
        # 初始 maxHeap,元素为 count ~ 字符,heapify 时自动根据 count 排序
        maxHeap = [[-cnt, char] for char, cnt in count.items()]
        heapq.heapify(maxHeap)
        
        # 为了间隔安插,我们需要知道当前字符的前一个字符是啥,于是初始化 prev 为空
        prev = None
        res = ""
        while maxHeap or prev:
            # 安插字符时,maxHeap 为空而 prev 还有元素,说明没有可用字符但还有等待间隔安插的字符——所以该字符满足不了间隔的题目要求,提前返回……
            if prev and not maxHeap:
                return ""
            
            cnt, char = heapq.heappop(maxHeap)
            res += char
            # maxHeap pop 一个字符后,说明已经安排了一个与 prev 值不同的字符,这时 prev 可以放回 maxHeap 循环;
            # 与此同时 prev 也需要重设一下……
            if prev:
                heapq.heappush(maxHeap, prev)
                prev = None
            # 更新 maxHeap 刚刚 pop 的元素 count:count 为 0 说明该元素已经完成安插可以销毁;count 不为 0 需要放入刚刚清空的 prev 等待时机重回 maxHeap 被安排……    
            cnt += 1
            if cnt:
                prev = [cnt, char]
                
        return res


Constraints

  • 1 <= s.length <= 500
  • s consists of lowercase English letters.


Big O

  • Time:O( n * logn )做了一遍循环 O(n),每次遍历时 maxHeap 需要整理一次 O(logn)
  • Space:O(26),字符串由 26 个小写英文字母组成,maxHeap 的长度最多为 26




测试

  • 当 s 无法满足相邻字符不相同时
  • 当 s 满足时
  • s 长度为 1 的边缘案例时……
  • ……



总结

  • 本题和 #621 安排任务 极其相似,本题可与 #621配套复习,理解 heap 解决间隔安排问题的原理和逻辑思路…


CC BY-NC-ND 2.0 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…
加载中…

发布评论