算法题-给定字符串,按照字符出现的频率从高到低依次打印出来

如给定‘asdsdss’  字符s出现4次,d出现2次,a出现一次,打印结果应为:ssssdda

以下是解体过程

package com.example.demo;

import java.util.*;

public class Deni {
    public static void main(String[] args) {
        String s = "aaffaawnnnwqqqoooooooqrrrrllllllllllrd";
        char[] chars = s.toCharArray();
        // 使用map统计字符出现的个数
        HashMap<Character, Integer> map = countCharMap(chars);
        Integer[] objects = map.values().toArray(new Integer[0]);
        // 首先排序
        quickSort(objects, 0, objects.length - 1);
        // 然后按照从大到小排序顺序组装字符
        combineCharBySort(chars, map, objects);
        // 打印组装好的字符
        for (int i = 0; i < chars.length; i++) {
            System.out.print(chars[i]);
        }
        System.out.println();
    }

    /**
     * 使用map统计字符出现的次数
     * @param chars 字符数组
     * @return map
     */
    private static HashMap<Character, Integer> countCharMap(char[] chars) {
        HashMap<Character, Integer> map = new HashMap();
        for (char aChar : chars) {
            if (map.get(aChar) == null) {
                map.put(aChar, 1);
            }else{
                map.put(aChar, map.get(aChar) + 1);
            }
        }
        return map;
    }

    /**
     * 组装要打印的字符数组
     * @param chars 字符数组
     * @param map map
     * @param objects 从大到小排序好的每个字符出现的个数
     */
    private static void combineCharBySort(char[] chars, HashMap<Character, Integer> map, Integer[] objects) {
        // 要存入的字符串下标
        int j = 0;
        for (int i = 0; i < objects.length - 1; i++) {
            for (Map.Entry<Character, Integer> characterIntegerEntry : map.entrySet()) {
                Character key = characterIntegerEntry.getKey();
                Integer value = characterIntegerEntry.getValue();
                if (value.equals(objects[i])) {
                    int count = j;
                    // 将当前相同的字符挨个存入数组
                    while (j - count < value) {
                        chars[j++] = key;
                    }
                    // 遍历过的字符从map中移除,降低遍历次数
                    map.remove(key);
                    break;
                }
            }

        }
    }

    /**
     * 快速排序
     * @param arr 数组
     * @param left 数组左下标
     * @param right 数组右下标
     */
    private static void quickSort(Integer[] arr, int left, int right){
        if (left >= right) {
            return;
        }
        // 排序并获取中间值(基准值)的下标
//        int mid = getMid(arr, left, right);
        int mid = getMid2(arr, left, right);
        // 递归排序左边的区间,注意:最后一位参数不能写成mid,否则会死循环
        quickSort(arr, left, mid - 1);
        // 递归排序右边的区间,中间的参数不能写为mid,否则会死循环
        quickSort(arr, mid + 1, right);

    }




    /**
     * 查找基准下标(巧妙使用数组下标排序)
     * @param arr 数组
     * @param left 左下标
     * @param right 右下标
     * @return 中值下标
     */
    private static int getMid2(Integer[] arr, int left, int right){
        int i = left;
        int pivot = arr[right];
        for (int j = left; j < right; j++) {
            if (arr[j] > pivot) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
                i++;
            }
        }
        int temp = arr[i];
        arr[i] = arr[right];
        arr[right] = temp;
        return i;
    }


    /**
     * 查到基准下标(排序)
     * @param arr 数组
     * @param left 数组左下标
     * @param right 数组右下标
     * @return 中值下标
     */
    private static int getMid(Integer[] arr, int left, int right) {
        int base = arr[left];
        while (left < right){
            // 从最右边开始查找小于基准点点值,如没有就将最右边的下标减1
            // (注意:判断条件必须是包含等于,否吃会死循环,因此快速排序不能保证两个等值的元素,排完循序后还保持原有循序,不是稳定的排序算法)
            while (left < right && arr[right] >= base) {
                right--;
            }
            // 找到小于基准点点值后交换
            arr[left] = arr[right];
            // 从左边开始查找大于基准值的元素,没有就将下标加1
            while (left < right && arr[left] <= base){
                left++;
            }
            // 找到大于基准点的值后交换
            arr[right] = arr[left];
        }
        // 最后将原来的基准值填充回来,此时的left就是基准值的下标(注意:left经过++操作已经不是原来的下标值了)
        arr[left] = base;
        return left;
    }

}

 


http://www.niftyadmin.cn/n/1702357.html

相关文章

Android测试提升效率批处理脚本(三)

前言&#xff1a; 前面放出过几次批处理&#xff0c;这次只放一个环境检查的被管理员给打回来了&#xff0c;不得不再找找几个有含金量的放出来&#xff0c;请看正文~~~ 目录 1、Android环境检查2、Android内存监控3、模拟蓝牙手柄事件一、Android环境检查 ECHO OFFECHO. …

sql injection violation, syntax error:

问题&#xff1a;uncategorized SQLException; SQL state [null]; error code [0]; sql injection violation, syntax error: ERROR. pos 826, line 38, column 15, token FROM : 具体原因&#xff1a;就是SQL片段末尾多了一个逗号&#xff0c;不过MySQL给出的这种提示也太模…

进程、线程、协程之概念理解

一、概念 1、进程 进程&#xff08;Process&#xff09;是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;是操作系统结构的基础。在早期面向进程设计的计算机结构中&#xff0c;进程是程序的基本执行实体&#xff1…

-XX:+DisableExplicitGC弊端

总结&#xff1a; 如果jvm参数中设置了-XX:DisableExplicitGC&#xff0c;那么代码中手动调用System.gc()就不会生效。而有些框架中因为是使用的堆外内存&#xff0c;必须手动调用System.gc()来释放。如果禁用掉就会导致堆外内存使用一直增长&#xff0c;造成内存泄露。 详解&…

Android知识点总结(知识点交汇点)

说明 文章都是转载自其他大神之手&#xff0c;看完能学到很多东西&#xff0c;这里主要讲解的是Android体系的相关知识点&#xff0c;本文会持续跟进更新。 1 Android service相关知识点 Android Service完全解析&#xff0c;关于服务你所需知道的一切(上) http://blog.csdn.ne…

一次帮同事排查Integer类型比较==的问题

同事要对一个集合做过滤&#xff0c;集合中的对象Sku中有两个Integer的属性&#xff0c;一个是商品的真实库存数量stockNum&#xff0c;一个是商品的预占库存occupyNum 要将所有真实库存数量与预占库存数量相等的数据、不相等的数据分别收集起来。 public class Sku {private L…

查看LINUX发行商版本与LINUX内核版本

查看LINUX发行商版本:[rootserver-mysql ~]# cat /etc/issue Red Hat Enterprise Linux Server release 6.3 (Santiago)[rootserver-mysql ~]# lsb_release -a LSB Version: :core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:print…

排查jar包冲突的方法

项目启动报错&#xff1a;java.lang.NoClassDefFoundError: com/fasterxml/classmate/members/ResolvedParameterizedMember org.springframework.beans.factory.BeanCreationException: Error creating bean with name org.springframework.web.servlet.mvc.method.annotatio…