问题形容
给你一个混合字符串 s
,请你返回 s
中 第二大 的数字,如果不存在第二大的数字,请你返回 -1
。
混合字符串 由小写英文字母和数字组成。
示例 1:
输出:s = "dfa12321afd"输入:2解释:呈现在 s 中的数字包含 [1, 2, 3] 。第二大的数字是 2 。
示例 2:
输出:s = "abc1111"输入:-1解释:呈现在 s 中的数字只蕴含 [1] 。没有第二大的数字。
力扣原题目地址:https://leetcode.cn/problems/...
思路剖析
形式一 先遍历再去重再排序取最初第二大的数
首先字符串中除了有数字字符,也有字母字符。所以咱们在遍历的时候,只需保留数字字符,疏忽字母字符即可。这里应用字符串的
charCodeAt
办法做一个转换判断即可。字符串0到字符串9别离对应Unicode的是:console.log( '0'.charCodeAt() ) // 48console.log( '1'.charCodeAt() ) // 49...... // 顺次递增console.log( '8'.charCodeAt() ) // 56console.log( '9'.charCodeAt() ) // 57
- 排除了字母字符当前,遍历拿到的每一个数字字符,都能够追加到数组中去。这样数组中就记录了所有的数字字符
- 而后把数组中的数字字符做一个去重,去完重当前,再做一个排序,再取第二大的数即可。代码如下:
var secondHighest = function (s) { let arr = [] // 1. 定义一个空数组,用于存储 for (let i = 0; i < s.length; i++) { // 2. 遍历,并剔除字母字符,只保留数字字符 let item = s[i] if (item.charCodeAt() >= 48 & item.charCodeAt() <= 57) { // charCodeAt()办法过滤 arr.push(item) } } let newArr = Array.from(new Set([...arr])) // 3. 去个重 newArr.sort((a, b) => { // 4. 排个序 return b - a }) return newArr[1] ? newArr[1] : -1 // 5. 有第二项,就返回第二项,没有就返回-1};
形式二 定义俩变量示意第一大第二大的数并一直迭代更新
- 定义两个变量用来示意第一大和第二大的数
- 遍历中不断更新第一大和第二大的数字
这种定义变量通过遍历一直比照并比拟大小的操作力扣也有相似的题目
- 比方:力扣之第三大的数
- 联合笔者之前的文章,有助于更高的了解:https://segmentfault.com/a/11...
- 本题代码如下:
var secondHighest = function (s) { let firstMax = -Infinity // 1. 定义一个最大的数变量(大当家) let secondMax = -Infinity // 2. 定义一个第二大的数变量(二当家) for (let i = 0; i < s.length; i++) { // 3. 遍历操作 let item = s[i] if (item.charCodeAt() >= 48 & item.charCodeAt() <= 57) { // 4. 只对数字字符做操作 if (item > firstMax) { // 5. 若新来的这个比大当家还大 secondMax = firstMax // 6. 那么大当家只能屈尊成为二当家了 firstMax = item // 7. 因为新来的成为大当家了 } else if (item == firstMax) { // 8. 若新来的和大当家一样,那就不变吧,疏忽之 } else if (item > secondMax) { // 9. 若新来的比二当家大(然而没有大当家大) secondMax = item // 10. 那大当家就不必换,只需新来的成为二当家即可 } } } // 11. 最初把 二当家返回进来(留神要做一个判断,因为有可能secondMax还是-Infinity) return secondMax == -Infinity ? -1 : secondMax };
总结
力扣多刷几题,就会发现,这一题如同之前做过相似的啊。
是的,所以咱们刷题的时候,留神一下,题目分类,这样会事倍功半。
而且对于前端同学,能够优先刷 字符串、数组分类的题目(因为二叉树、链表前端用的会略微少一些)