壹 ❀ 引

本题来自LeetCode1370. 上升下降字符串,难度简单,是一道考察对于字符串遍历熟练度的题目,题目描述如下:

给你一个字符串 s ,请你根据下面的算法重新构造字符串:

从 s 中选出 最小 的字符,将它 接在 结果字符串的后面。

从 s 剩余字符中选出 最小 的字符,且该字符比上一个添加的字符大,将它 接在 结果字符串后面。

重复步骤 2 ,直到你没法从 s 中选择字符。

从 s 中选出 最大 的字符,将它 接在 结果字符串的后面。

从 s 剩余字符中选出 最大 的字符,且该字符比上一个添加的字符小,将它 接在 结果字符串后面。

重复步骤 5 ,直到你没法从 s 中选择字符。

重复步骤 1 到 6 ,直到 s 中所有字符都已经被选过。

在任何一步中,如果最小或者最大字符不止一个 ,你可以选择其中任意一个,并将其添加到结果字符串。

请你返回将 s 中字符重新排序后的 结果字符串 。

示例 1:

输入:s = "aaaabbbbcccc"
输出:"abccbaabccba"

解释:第一轮的步骤 1,2,3 后,结果字符串为 result = "abc"

第一轮的步骤 4,5,6 后,结果字符串为 result = "abccba"

第一轮结束,现在 s = "aabbcc" ,我们再次回到步骤 1

第二轮的步骤 1,2,3 后,结果字符串为 result = "abccbaabc"

第二轮的步骤 4,5,6 后,结果字符串为 result = "abccbaabccba"

示例 2:

输入:s = "rat"
输出:"art"

解释:单词 "rat" 在上述算法重排序以后变成 "art"

示例 3:

输入:s = "leetcode"
输出:"cdelotee"

示例 4:

输入:s = "ggggggg"

输出:"ggggggg"

示例 5:

输入:s = "spo"
输出:"ops"

提示:

1 <= s.length <= 500

s 只包含小写英文字母。

让我们简单分析题意,然后实现它。

贰 ❀ 桶排序与字符串常规API

题目要求其实并不复杂,给定一个全部是小写字母的字符串,然后对此字符串进行取值拼接操作。我们先取当前字符串中的最小字符(每个字符只能使用一次),拼到一个空字符串上,然后继续找第二小的字符串,继续拼接操作。比如aab第一次取最小是a,那么第二次取最小时其实取得是b,因为这里的最小的定义是比上次大但在剩余字符串中最小。直到取不到最小之后,我们又开始取剩余字符串最大的字符,继续拼接操作,然后取第二大的字符继续拼接,当找不到符合条件的字符串之后,再执行前面的取最小操作,直到字符串被取空。

aabbcc为例,它的过程其实就是这样:

因为题目说明只包含小写字母,因此可能存在的字符情况一共也就16种,我们完全可以统计出a-z每个字符的出现频率,然后取最小就从左往右遍历数组取,取一个记得把这个字符串的数字减一,遍历到头后说明取小操作结束。紧接着从右往左遍历,开始取最大操作,重复上述操作,直到没有字符可取为止。

因此到这里我们就可以使用桶排序,我们可以创建一个长度为26的数组,数组下标0表示a的位置,小标1表示字母b的位置,以这种方式来把所有字母次数都统计一次,具体怎么做呢?

字符串中有一个API叫charCodeAt,它用于获取一个字符的Unicode编码,比如字母a的编码为:

'a'.charCodeAt(0);//97
'z'.charCodeAt(0);//122

你会发现122-97=250-25一共正好26个数字,我们可以用每个字符串的编码减去97,比如'a'.charCodeAt(0)-97 = 0,它不就正好对应了数组下标0的位置,通过这种方式,我们就可以得到每个字符出现的次数,以及有序的与数组下标对应了。

问题又来了,假设我们得到了最终数组[2,2,2],其实就是abc分别都出现了2次,当我们遍历到数组某个下标,知道它的值大于0,那就表示还有可以使用的字母,但是我们将这个数组的下标反向解析成字符串呢?其实与charCodeAt对应还有个API叫fromCharCode,它能将一个Unicode码反向解析成字符串,比如:

String.fromCharCode(97+0);//a
String.fromCharCode(97+1);//b

而上述代码所加的数字,其实就是我们遍历到的当前的下标 i 。

OK,解释了这些,我们可以来实现这段代码:

/**
* @param {string} s
* @return {string}
*/
var sortString = function (s) {
// 创建一个有26个位置的空桶
const bucket = new Array(26).fill(0);
for (let i = 0; i < s.length; i++) {
// 统计每个字母出现的次数
bucket[s.charCodeAt(i) - 97]++;
};
let res = '';
let len = s.length;
while (len > 0) {
// 取最小操作
for (let i = 0; i < 26; i++) {
// 如果有值,说明有字母可以使用
if (bucket[i] > 0) {
// 拼接字符串
res += (String.fromCharCode(i + 97));
// 字符串都是一次性的,用了得减掉
bucket[i]--;
// 我们得保证整体的字符串长度也在递减,这样才知道什么时候字符串全部用完了。
len--;
}
}
//取最大操作
for (let i = 25; i >= 0; i--) {
if (bucket[i] > 0) {
res += (String.fromCharCode(i + 97));
bucket[i]--;
len--;
}
}
}
return res;
};

那么本题就说到这里了

JS Leetcode 1370. 上升下降字符串 题解分析,桶排序与charCodeAt fromCharCode妙用的更多相关文章

  1. C#版 - Leetcode 13. 罗马数字转整数 - 题解

    C#版 - Leetcode 13. 罗马数字转整数 - 题解 Leetcode 13. Roman to Integer 在线提交: https://leetcode.com/problems/ro ...

  2. C#版[击败100.00%的提交] - Leetcode 6. Z字形变换 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  3. js与java正则表达式处理字符串问题

    在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要.正则表达式就是用于描述这些规则的工具.换句话说,正则表达式就是记录文本规则的代码.合理使用正则表达式确实会为程序员省去很多字 ...

  4. js如何将纯数字字符串转换为long型

    1.js如何将纯数字字符串转换为long型? js 中 int的存储位数?最大十进制数表示是多少? 精度http://www.jb51.net/article/59808.htm 整数(不使用小数点或 ...

  5. asp.net使用unescape读取js escape编码过的字符串

    escape() 是JavaScript的编码函数 例子:var esstring=escape("helloworld"); 为了防止数据传输读取中出现乱码现象,字符串往往要用J ...

  6. js MD5加密后的字符串

    js MD5加密后的字符串 <script language="JavaScript"> /************************************** ...

  7. JSON(二)——JavaScript中js对象与JSON格式字符串的相互转换

    首先我们来看一下js中JSON格式的字符串 var JSONStr1 = "{\"name\" : \"张三\"}"; 注意以下的写法不是j ...

  8. C#版 - Leetcode 633. 平方数之和 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  9. C#版 - Leetcode 593. 有效的正方形 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  10. C#版 - Leetcode 414. Third Maximum Number题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

随机推荐

  1. shell脚本(1)-shell介绍

    一.shell介绍 1.什么是shell shell是c语法编写的,是用户和liunx内核沟通的桥梁,即是命令语法,也是解释性编程语言. 内核处理的都是二进制,而用户处理的都是高级语法,系统开发人员可 ...

  2. Oracle表结构&数据类型&约束

    1.Oracle 表结构 1.1.创建表名的规范 推荐以"t_xxx" 不能含有"+- "等非法字符,eg:sql create table "t-1 ...

  3. [转帖]TIDB - 使用BR工具进行数据热备份与恢复

    一.BR工具 BR 全称为 Backup & Restore,是 TiDB 分布式备份恢复的命令行工具,用于对 TiDB 集群进行数据备份和恢复.BR 只支持在 TiDB v3.1 及以上版本 ...

  4. [转帖]tidb 搭建私有镜像库

    https://docs.pingcap.com/zh/tidb/stable/tiup-mirror 在构建私有云时,通常会使用隔离的网络环境,此时无法访问 TiUP 的官方镜像.因此,TiUP 提 ...

  5. [转帖]《AWK程序设计语言》笔记(1)—— AWK入门与简单案例

    原文为 <The AWK Programming Language>,GitHub上有中译版,不过有些内容翻译的比较奇怪,建议跟原版对照着看 https://github.com/wuzh ...

  6. 【转帖】ESXi 6.x 安装storcli监控raid卡状态

    https://b2b.baidu.com/land?id=744541c6188f7937d6dc97d6fb9142ff10 脚本宝典收集整理的这篇文章主要介绍了ESXi 6.x 安装storcl ...

  7. [转帖]Arm发布CortexX4,功耗可降低40%

    https://www.eet-china.com/mp/a224124.html ARM 发布了新一代的移动处理器内核,包括 Cortex-X4.Cortex-A720.Cortex-A520,预计 ...

  8. [转帖]Linux shell 单引号和双引号

    https://www.cnblogs.com/airoot/p/15324883.html 在编写shell脚本的时候经常会用到引号,有些时候却老是忘记单引号和双引号之间的区别,所以就整理一下供以后 ...

  9. [转帖]Linux下的I/O复用与epoll详解

    https://blog.csdn.net/weixin_39094034/article/details/110393127 前言 I/O多路复用有很多种实现.在linux上,2.4内核前主要是se ...

  10. 【深度学习项目一】全连接神经网络实现mnist数字识别

    相关文章: [深度学习项目一]全连接神经网络实现mnist数字识别 [深度学习项目二]卷积神经网络LeNet实现minst数字识别 [深度学习项目三]ResNet50多分类任务[十二生肖分类] 『深度 ...