• letcode每日一题-重构字符串


    周末去了动物园,虽然我几乎被冻成了狗,但还是好开心呀,今天开开心心的来更新啦!!!

    题目描述:

    方法:基于最大堆的贪心算法
    维护最大堆存储字母,堆顶元素为出现次数最多的字母。首先统计每个字母的出现次数,然后将出现次数大于 00 的字母加入最大堆。

    当最大堆的元素个数大于 11 时,每次从最大堆取出两个字母,拼接到重构的字符串,然后将两个字母的出现次数分别减 11,并将剩余出现次数大于 00 的字母重新加入最大堆。由于最大堆中的元素都是不同的,因此取出的两个字母一定也是不同的,将两个不同的字母拼接到重构的字符串,可以确保相邻的字母都不相同。

    如果最大堆变成空,则已经完成字符串的重构。如果最大堆剩下 11 个元素,则取出最后一个字母,拼接到重构的字符串。

    对于长度为 nn 的字符串,共有 n/2n/2 次每次从最大堆取出两个字母的操作,当 nn 是奇数时,还有一次从最大堆取出一个字母的操作,因此重构的字符串的长度一定是 nn。

    当 nn 是奇数时,是否可能出现重构的字符串的最后两个字母相同的情况?如果最后一个字母在整个字符串中至少出现了 22 次,则在最后一次从最大堆取出两个字母时,该字母会先被选出,因此不会成为重构的字符串的倒数第二个字母,也不可能出现重构的字符串最后两个字母相同的情况。

    因此,在重构字符串可行的情况下,基于最大堆的贪心算法可以确保得到正确答案。
    实现代码如下:

    
    public String reorganizeString(String S) {
            int[] charCount=new int[26];
            //统计字符出现的次数
            for(int i=0;i<S.length();i++){
                int index=S.charAt(i)-'a';
                charCount[index]++;
            }
            //创建一个从大到小排序的队列
            PriorityQueue<Character> queue=new PriorityQueue<>((o1,o2)->{
                if(charCount[o1-'a']>charCount[o2-'a']){
                    return -1;
                }
                if(charCount[o1-'a']<charCount[o2-'a']){
                    return 1;
                }
                return 0;
            });
            //把字符放进队列中
            for(int i=0;i<charCount.length;i++){
                if(charCount[i]!=0){
                    queue.offer((char)(i+'a'));
                }
            }
            StringBuilder result=new StringBuilder();
            while (queue.size()>1){
                //出现频率最高的字符
                char max_count_char=queue.poll();
                //出现频率第二高的字符
                char second_count_char=queue.poll();
                int maxIndex=max_count_char-'a';
                int secondIndex=second_count_char-'a';
                //重新构建字符串
                if(result.length()==0 || result.charAt(result.length()-1)!=max_count_char){
                    result.append(max_count_char);
                    charCount[maxIndex]--;
                }
                int minLen=Math.min(charCount[maxIndex],charCount[secondIndex]);
                for(int i=0;i<minLen;i++){
                    result.append(second_count_char).append(max_count_char);
                }
                //--重新构建字符串结束
                charCount[maxIndex]-=minLen;
                charCount[secondIndex]-=minLen;
                if(charCount[maxIndex]>0){
                    queue.offer(max_count_char);
                }
                if (charCount[secondIndex]>0){
                    queue.offer(second_count_char);
                }
            }
            if(queue.size()==0){
                return result.toString();
            }
            if(queue.size()==1){
                char last=queue.poll();
                if(charCount[last-'a']==1 && result.charAt(result.length()-1)!=last){
                    result.append(last);
                    return result.toString();
                }
            }
            return "";
        }
    
    
  • 相关阅读:
    腾讯企业微信机器人通知
    python 协程、异步、async
    pytest获取测试用例执行结果(钩子函数:pytest_runtest_makereport)
    pytest hook使用
    sqlalchemy backref解释
    docker 启动mysql 并本地连接
    Flask用paginate实现数据分页
    在flask中使用flaskmigrate管理数据库
    ExtAspNet v2.3.5
    Caliburn Micro下轻松实现ListView的全选功能
  • 原文地址:https://www.cnblogs.com/MissWX/p/14061399.html
Copyright © 2020-2023  润新知