算法題-給定字符串,按照字符出現的頻率從高到低依次打印出來

如給定‘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;
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章