【LeetCode - 358】 K 距离间隔重排字符串

1、题目描述

在这里插入图片描述

2、解题思路

  先统计所有字符出现的次数,存入一个 HashMap 中,接着按照重复次数 (char,count) 从大到小构建一个大顶堆,把 map 中的元素装入大顶堆中。

  创建一个 StringBuilder 对象 sb。

  创建一个普通队列变量 queue 同步记录已经加入到 sb 中的字符。

  循环遍历大顶堆的字符:

  1、取出一个字符 c ,把它加入到 sb 中;

  2、把 c 的重复次数减一,加入到一个普通队列 queue 中;

  3、判断 queue 中的元素个数是否为 k,如果是,说明 sb 中距离上一个字符 c 已经插入了 k 个字符了,现在字符 c 可以再出现一次了,把 queue 队首元素放入大顶堆。

  当大顶堆没有元素了:

  1、sb 的长度和 s 一样,说明重构完成,返回 sb.toString();

  2、sb 的长度和 s 不一样,说明还有些字符挂在 queue 中,没有装入大顶堆,说明有些字符无法间隔 k 个距离。

3、解题代码

class Solution {
    public String rearrangeString(String s, int k) {
        if (k <= 1) {
            return s;
        }
        HashMap<Character, Integer> map = new HashMap<>();
        // 大顶堆
        PriorityQueue<Map.Entry<Character, Integer>> maxHeap = new PriorityQueue<>((a, b) -> b.getValue() - a.getValue());
        for (Character c : s.toCharArray()) {
            // 遍历字符,统计字符的出现次数
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        maxHeap.addAll(map.entrySet()); // 装入大顶堆,按照字符重复次数作为比较
        StringBuilder sb = new StringBuilder(s.length());
        Queue<Map.Entry<Character, Integer>> queue = new LinkedList<>();
        while (!maxHeap.isEmpty()) {
            Map.Entry<Character, Integer> currentEntry = maxHeap.poll();    // 从大顶堆取出重复次数最多的字符
            sb.append(currentEntry.getKey());
            currentEntry.setValue(currentEntry.getValue() - 1); // 用掉一个字符,次数减一
            queue.offer(currentEntry);  // 放入到queue中,因为k距离后还要用。
            if (queue.size() == k) {
                // queue的大小到达了k,也就是说我们已经越过了k个单位,在结果中应该要出现相同的字母了
                Map.Entry<Character, Integer> entry = queue.poll();
                if (entry.getValue() > 0) {
                    // 该字符的重复次数大于 0,则添加入大顶堆中,要是0那还加它干嘛
                    maxHeap.add(entry);
                }
            }
        }
        // 退出 while 循环就是大顶堆已经没有元素了,如果此时 sb 的长度没有还原,说明还有元素挂在 queue 中
        // 即 queue.size() == k 这个条件没有完全满足,即存在一些字符无法间隔 k 个距离
        return sb.length() == s.length() ? sb.toString() : "";
    }
}
  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值