​LeetCode刷题实战358:K 距离间隔重排字符串

共 8277字,需浏览 17分钟

 ·

2021-08-24 17:30

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 K 距离间隔重排字符串,我们先来看题面:
https://leetcode-cn.com/problems/count-numbers-with-unique-digits/

Given a non-empty string s and an integer k, rearrange the string such that the same characters are at least distance k from each other.


All input strings are given in lowercase letters. If it is not possible to rearrange the string, return an empty string "".

给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少为 k。

所有输入的字符串都由小写字母组成,如果找不到距离至少为 k 的重排结果,请返回一个空字符串 “”。

示例


示例 1:

输入: s = “aabbcc”, k = 3
输出: “abcabc”
解释: 相同的字母在新的字符串中间隔至少 3 个单位距离。

示例 2:

输入: s = “aaabc”, k = 3
输出: “”
解释: 没有办法找到可能的重排结果。

示例 3:

输入: s = “aaadbbcc”, k = 2
输出: “abacabcd”
解释: 相同的字母在新的字符串中间隔至少 2 个单位距离。


解题

https://blog.csdn.net/weixin_39029194/article/details/108190951

贪心法,每次尽量取频次大的字母加入结果
1.统计每个字母出现的次数,存入map
2.把所有的字母按照频次排序存入队列
3.每次从队列中取k个最大频次的字母,加入结果字符串。
4.然后相应频次减一后再放回队列。每次字符串长度要减掉K。最后一次不够K个,就取最后一次遍历的字符串的长度的字母加入结果字符串。

class Solution {
    public String rearrangeString(String str, int k) {
        if (k == 0) {
            return str;
        }
        // 1.构建单词与频率的映射
        Map<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (map.containsKey(ch)) {
                map.put(ch ,map.get(ch) + 1);
            } else {
                map.put(ch, 1);
            }
        }
        // 2.将所有出现的字母按照频率排序
        PriorityQueue<Character> queue = new PriorityQueue<>((c1, c2) -> {
            if (map.get(c2).intValue() != map.get(c1).intValue()) {
                return map.get(c2) - map.get(c1);
            } else {
                // 如果频率相同,按字典排序
                return c1.compareTo(c2);
            }
        });
        // 把字符放入队列,频率大的在前面
        for (char c: map.keySet()) {
            queue.offer(c);
        }
        // 试图构建字符串
        StringBuilder sb = new StringBuilder();
        // 初始字符长度
        int len = str.length();
        // 3. 把字符按出现次数多的字符开始,把每一个字符插入到间隔中
        while (!queue.isEmpty()) {
            List<Character> tempChars = new ArrayList<>();
            // 得到较小的数(最后剩下的一截可能不够K)
            int n = Math.min(k, len);
            // 从queue里取出TopN位数字,填充每一个间隔区间
            for (int i = 0; i < n; i++) {
                // 在个数为N的间隔区间里,剩下的不重复的字符串已经用完了,那么必然构造不出间隔为N的无重复字符串了,
                // 也就是在这个区间里必然有重复的字母,到这里就无法再继续构造了
                if (queue.isEmpty()) {
                    return "";
                }
                // 取出这个字符
                char ch = queue.poll();
                sb.append(ch);
                // 取出这个字符,相应频次要减1
                map.put(ch, map.get(ch) - 1);
                // 这个字符还有剩余,就加进来tempChars,重新放到queue里,进行下一次的遍历
                if (map.get(ch) > 0) {
                    tempChars.add(ch);
                }
                // 已经取过了,字符长度减1
                len--;
            }

            // 4.每个字母减过一次了,把还有剩余次数的字母再次加入到queue里,继续下一次的循环
            for (Character tempChar : tempChars) {
                queue.offer(tempChar);
            }
        }

        return sb.toString();
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        String res = solution.rearrangeString("aabbcc", 3);
        String res2 = solution.rearrangeString("aaabc", 3);
        String res3 = solution.rearrangeString("aaadbbcc", 2);
        System.out.println(res);
        System.out.println(res2);
        System.out.println(res3);
    }
}


好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力 。

上期推文:

LeetCode1-340题汇总,希望对你有点帮助!
LeetCode刷题实战341:扁平化嵌套列表迭代器
LeetCode刷题实战342:4的幂
LeetCode刷题实战343:整数拆分
LeetCode刷题实战344:反转字符串
LeetCode刷题实战345:反转字符串中的元音字母
LeetCode刷题实战346:数据流中的移动平均值
LeetCode刷题实战347:前 K 个高频元素
LeetCode刷题实战348:设计井字棋
LeetCode刷题实战349:两个数组的交集
LeetCode刷题实战350:两个数组的交集 II
LeetCode刷题实战351:安卓系统手势解锁
LeetCode刷题实战352:将数据流变为多个不相交区间
LeetCode刷题实战353:贪吃蛇
LeetCode刷题实战354:俄罗斯套娃信封问题
LeetCode刷题实战355:设计推特
LeetCode刷题实战356:直线镜像

浏览 79
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报