我是靠谱客的博主 舒心果汁,最近开发中收集的这篇文章主要介绍LeetCode-451. 根据字符出现频率排序题目解题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例 1:

输入:
“tree”
输出:
“eert”
解释:
'e’出现两次,'r’和’t’都只出现一次。
因此’e’必须出现在’r’和’t’之前。此外,"eetr"也是一个有效的答案。

示例 2:

输入:
“cccaaa”
输出:
“cccaaa”
解释:
'c’和’a’都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。

示例 3:

输入:
“Aabb”
输出:
“bbAa”
解释:
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。

注意’A’和’a’被认为是两种不同的字符。

解题

  • 使用字符数组记录每个字符出现的频次
  • 设定频率高的值就大, 对字符数组进行三路快排, 降序排列, 代码如下:
/**
 * 451. 根据字符出现频率排序
 */
class Solution {
    private Random random = new Random();

    public String frequencySort(String s) {
        char[] chars = s.toCharArray();
        // 记录每个字符出现的频次, 数字下标为字符ASCII码, LeetCode这题的测试用例128已经够用了
        int[] freq = new int[128];
        // 遍历字符数组, 计算每个字符出现的频次, 这一步时间复杂度O(n)
        for (int i = s.length() - 1; i >= 0; i--) {
            freq[chars[i]]++;
        }

        // 对chars数组进行三路快排, 设定频次越高的字符值越大,频次相等时再按照字符ASCII码进行比较
        // 排序这一步时间复杂度为O(nlogn), 所以整个算法的时间复杂度是O(nlogn)
        quicksort3Ways(chars, 0, s.length() - 1, freq);
        // 排序完成之后
        return  new String(chars);
    }

    /**
     * 三路快排, 递归算法, 对chars数组的[l...r]前闭后闭区间进行排序
     * @param chars : 要排序的字符数组
     * @param l : 数组左边界
     * @param r : 数组右边界
     * @param freq : 字符出现频次, 设定字符大小与频次高低一致
     */
    private void quicksort3Ways(char[] chars, int l, int r, int[] freq){
        // 递归终止条件,只有一个元素时默认数组是有序的
        if (r - l < 1) {
            return;
        }

        // 选取标定点, 随机选取, 避免数组本身是有序的导致快排性能下降
        int pivotIndex = random.nextInt(r - l + 1) + l;
        swap(chars, l, pivotIndex);
        char pivot = chars[l];
        // 设定chars[l+1...left] < pivot, chars[left + 1, i) == pivot, chars[right, r] < pivot
        int left = l, right = r + 1, i = l + 1;
        while(i < right){
            // 大于pivot的元素
            if (compare(chars[i], pivot, freq) > 0) {
                swap(chars, left + 1, i);
                left++;
                i++;
            // 小于pivot的元素
            } else if (compare(chars[i], pivot, freq) < 0) {
                swap(chars, right - 1, i);
                // right - 1的元素还没有遍历, 所以这里只需要right--, 并不用i++
                right--;
            } else {
                i++;
            }

        }

        // chars[l]==pivot, 所以最后需要将l与left交换位置
        swap(chars, l , left);
        // 递归对小于pivot的元素再进行排序
        quicksort3Ways(chars, l, left, freq);
        // 递归对大于pivot的元素再进行排序
        quicksort3Ways(chars, right, r, freq);
    }

    public int compare(char c1, char c2, int[] freq) {
        if (freq[c1] == freq[c2]){
            return c1 - c2;
        }
        return freq[c1] - freq[c2];
    }

    /**
     * 对数组chars数组中index1,index2位置的两个元素进行交换
     * @param chars
     * @param index1
     * @param index2
     */
    private void swap(char[] chars, int index1, int index2){
        char temp = chars[index1];
        chars[index1] = chars[index2];
        chars[index2] = temp;
    }

}

最后

以上就是舒心果汁为你收集整理的LeetCode-451. 根据字符出现频率排序题目解题的全部内容,希望文章能够帮你解决LeetCode-451. 根据字符出现频率排序题目解题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部