java数据结构与算法刷题-----LeetCode451. 根据字符出现频率排序

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

文章目录

    • 1. hash统计出现次数后排序
    • 2. 桶排序

在这里插入图片描述

1. hash统计出现次数后排序

解题思路:时间复杂度O( ) ,空间复杂度 O ( ),空间复杂度O( ),空间复杂度O()
  1. 通过hash表统计每个字符的出现次数,时间复杂度O( n n n)
  2. 对hash表按照出现次数降序排序,时间复杂度O( k ∗ l o g 2 k k*log_2{k} klog2k)是快速排序的时间复杂度。其中k是hash大小,也就是字符串中不重复的字母个数

如果使用数组作为hash表,不使用HashMap的话,则不需要排序

  1. 然后依次将最大出现次数的字符,拼接起来,输出。正好是按照排序好的hash表进行输出。O( k k k)

使用数组作为hash表,虽然不需要排序,但是每次都得遍历整个hash表找到出现次数最多的字符。因此时间复杂度O( n ∗ k n*k nk)其中n是字符串大小,k是hash表大小。我们需要找到n个字符拼接为结果字符串,每次都需要完整遍历hash表(长度为k)找到出现次数最多的

  1. 因此时间复杂度为
  1. 直接使用HashMap,时间复杂度O( n + k ∗ l o g 2 k n+k*log_2{k} n+klog2k),空间复杂度O( n + k n+k n+k).另外快速排序也需要额外栈空间O( l o g 2 k log_2{k} log2k)
  2. 使用数组作为hash表,时间复杂度O( n + n ∗ k n+n*k n+nk),空间复杂度O(n+k).

使用数组作为hash表所需大小:
字符串包含大小写字母和数字,ASCII码如下:A = 65,Z = 90. a = 97,z = 122,0 = 48,9 = 57
因此hash表大小为123即可(下标从0到122)。并且从48开始,前面47的下标是没有用的

代码:选用数组作为hash,因为这样更难,做题情况下,比使用HashMap效率高很多(工作场景下没什么区别)。但是工作场景中,要使用HashMap。

在这里插入图片描述

class Solution {
    public String frequencySort(String s) {
        int[] list = new int[123];//hash表
        char[] chars = s.toCharArray();//获取字符数组
        for (int i = 0; i < chars.length; i++) {//统计每个字符出现的次数
            int n = (int) chars[i];//获取当前字符的ASCII码
            list[n]++;//对应hash位置+1
        }
        int index = 0;//结果字符数组的下标
        while (index < chars.length) {
            int max = 0;//保存最大值
            char target = ' ';//保存出现次数最多的字符
            for (int i = 48; i < list.length; i++) {//遍历hash表
                if (list[i] > max) {//如果当前字符出现次数更多
                    max = list[i];//保存这个次数
                    target = (char) i ;//让target指向这个字符
                }
            }
            for (int j = 0; j < max; j++) {//将其拼接到字符数组中
                chars[index++] = target;
            }
            list[target] = 0;//hash表中已经输出的字符归0
        }
        return String.valueOf(chars);
    }
}

2. 桶排序

解题思路:时间复杂度O( n + k n+k n+k),空间复杂度O( n + k n+k n+k)
  1. 先通过hash表统计每个字符的出现次数,时间复杂度O( n n n)
  2. 然后按照出现次数,将字符放入对应桶中。时间复杂度O( k k k)

桶保存的是对应出现次数的字符。例如1号桶保存出现1次的字符,2号桶保存出现次数为2的字符

  1. 然后从后往前遍历桶(出现次数高的先拼接到字符串)。时间复杂度O( k k k)

记住,当前是几号桶,取出的字符就出现几次。因此我们拼接字符串时,要将取出的字符每个都拼接对应桶的次数

代码:因为使用了StringBuilder,做题场景下的效率反而比方法1慢,但是实际工作场景中,肯定是这个方法的时间复杂度更优

在这里插入图片描述

class Solution {
   public String frequencySort(String s) {
        char[] charArray = s.toCharArray();
        int[] freq = new int[128]; // 使用128大小的数组,考虑到ASCII码表
        StringBuilder[] buckets = new StringBuilder[s.length() + 1];//桶,个数为字符串中字符个数+1
        // 统计字符出现频率
        for (char c : charArray) freq[c]++;
        // 将字符按照频率放入对应的桶中,出现次数是几,就放入几号桶
        for (int i = 48; i < 128; i++) {
            if (freq[i] > 0) {//如果当前字符出现次数>0
                //放入对应出现次数的桶中,例如当前字符出现3次,就放入3号桶
                if (buckets[freq[i]] == null) buckets[freq[i]] = new StringBuilder();//如果当前桶为空,先创建桶
                buckets[freq[i]].append((char)i);//然后将字符添加到桶中
            }
        }
        // 构建结果字符串
        StringBuilder result = new StringBuilder();
        for (int i = buckets.length-1; i > 0; i--) {//从后往前遍历桶
            if (buckets[i] != null) {//先查看,统计出现次数最高字符的桶
                for (char c : buckets[i].toString().toCharArray()) {//依次取出桶中字符
                    for (int j = 0; j < i; j++) {//当前是i号桶,这个字符需要添加i次,因为i是它的出现次数
                        result.append(c);
                    }
                }
            }
        }
        return result.toString();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/483428.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot的牙科就诊管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的牙科就诊管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍: 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c…

<Linux> 线程池

目录 前言&#xff1a; 一、线程池概念 &#xff08;一&#xff09;池化技术 &#xff08;二&#xff09;优点 &#xff08;三&#xff09;应用场景 二、线程池的实现 &#xff08;一&#xff09;线程池_V1&#xff08;朴素版&#xff09; &#xff08;二&#xff09;线…

GaussDB WDR分析之集群报告篇

AWR报告目前已经成为Oracle DBA分析问题&#xff0c;定位故障最为重要的报告&#xff0c;阅读与分析AWR报告的技能也是Oracle DBA必备的技能。国产数据库为了提高运维便捷性&#xff0c;都在做类似Oracle AWR报告的模仿&#xff0c;只不过由于指标体系不够完善&#xff0c;因此…

列强,瓜分台积电!

特朗普曾说&#xff0c;台积电是他能想到的&#xff0c;唯一一家被迫停产会导致全球经济萧条的企业。 如今&#xff0c;美国、日本、欧洲争相发出巨额补贴&#xff0c;“邀请”台积电到当地设厂&#xff0c;对这家唯一重要的企业发起了攻势。 2022年12月6日&#xff0c;美国…

【LeetCode: 120. 三角形最小路径和 + 动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

WEB DDOS的安全策略

近年来网络攻击的数量和频率急剧上升&#xff0c;针对Web应用程序的DDoS海啸攻击就是其中增长非常迅速的一个种类。过去常见的HTTP/S洪水攻击正在大范围的转变为更难对付的Web DDoS海啸攻击&#xff0c;网络安全空间攻防对抗越演越烈&#xff0c;企业用户面临更加严峻的网络安全…

思通舆情 是一款开源免费的舆情系统 介绍

思通舆情 是一款开源免费的舆情系统。 支持本地化部署&#xff0c;支持在线体验。 支持对海量舆情数据分析和挖掘。 无论你是使用者还是共同完善的开发者&#xff0c;欢迎 pull request 或者 留言对我们提出建议。 您的支持和参与就是我们坚持开源的动力&#xff01;请 sta…

[java基础揉碎]理解main方法语法

目录 深入理解main方法 解释main方法的形式: main方法的特别说明: main方法的动态传值: 深入理解main方法 解释main方法的形式: public static void main(String[] args){} 1.mian方法是虚拟机调用 2. java虚拟机需要调用类的main()方法&#xff0c;所以该方法的访问权…

每日一题 --- 移除链表元素[力扣][Go]

移除链表元素 题目&#xff1a;203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xf…

【源码】I.MX6ULL移植OpenCV

编译完成的源码&#xff1a; git clone https://gitee.com/wangyoujie11/atkboard_-linux_-driver.git 1.下载源码放在自己的opecv源码目录下 2.QTOpenCV工程代码放置的位置 3.更改.pro工程文件的opencv地址 4.使用命令行编译 前提是自己环境中已经配置好arm-qt的交叉编译…

【Redis知识点总结】(六)——主从同步、哨兵模式、集群

Redis知识点总结&#xff08;六&#xff09;——主从同步、哨兵模式、集群 主从同步哨兵集群 主从同步 redis的主从同步&#xff0c;一般是一个主节点&#xff0c;加上多个从节点。只有主节点可以接收写命令&#xff0c;主节点接收到的写命令&#xff0c;会同步给从节点&#…

Github 2024-03-24php开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-24统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量PHP项目10JavaScript项目1Nextcloud服务器:安全的数据之家 创建周期:2796 天开发语言:PHP, JavaScript协议类型:GNU Affero General Public…

【数据结构】考研真题攻克与重点知识点剖析 - 第 1 篇:绪论

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

IDDR、ODDR、IDEALY2和ODELAY2详解

文章目录 前言一、IDDR原语二、ODDR原语三、IDELAYCTRL原语四、IDELAY原语4.1、参数配置 &#xff1a;4.2、端口说明 &#xff1a;4.3、延时控制时序图 五、ODELAY原语 前言 本文参考XILINX手册UG471 一、IDDR原语 参考xilinx手册UG471 IDDR #(.DDR_CLK_EDGE ("SAME_…

【C++11】:统一的列表初始化|声明|STL变化

​ &#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;マイノリティ脈絡—ずっと真夜中でいいのに。 0:24━━━━━━️&#x1f49f;──────── 4:02 &#x1f504; …

已知屏幕分辨率和屏幕尺寸,JavaScript如何计算屏幕PPI像素密度

返回主目录:OpenLayers扩展组件系列汇总目录:常用OpenLayers地图扩展组件ol-ext、ol-cesium、ol-layerswitcher、ol-geocoder和ol-wind等扩展库 前言 本章作为补充章,用于讲解使用ol-ext组件的前置知识。 要想知道 PPI 是什么,我们需要先理解“像素”这个概念,那么什么是…

【C++算法】洛谷P1102:A-B数对,思路,lower_bound,upper_bound,二分答案,代码详解

文章目录 1&#xff09;解题思路2&#xff09;三种情况3&#xff09;代码 题目链接&#xff1a;P1102 A-B 数对 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 1&#xff09;解题思路 这道题要求我们在序列中找到 A − B C A-BC A−BC 的数对的个数&#xff0c;下标不同的数…

注解总结,Java中的注解,springboot中的注解

注解总结 1、Junit 开始执行的方法&#xff1a;初始化资源&#xff0c;执行完之后的方法&#xff1a;释放资源 测试方法&#xff0c;必须是&#xff1a;公有、非静态、无参无返回值的 在一个类中&#xff0c;可以定义多个测试方法&#xff0c;每个测试方法可以单独运行&#…

XUbuntu22.04之安装Plantuml(二百二十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

llvm后端

SelectionDAGBuilder是LLVM&#xff08;Low Level Virtual Machine&#xff09;编译器中的一个重要组件&#xff0c;它负责将LLVM中间表示&#xff08;Intermediate Representation&#xff0c;IR&#xff09;转换为SelectionDAG&#xff08;选择有向无环图&#xff09;的形式。…