字符串中第二大的数字

标签: 哈希表 字符串

难度: Easy

给你一个混合字符串 s ,请你返回 s 中 第二大 的数字,如果不存在第二大的数字,请你返回 -1 。

混合字符串 由小写英文字母和数字组成。

 

示例 1:

输入:s = "dfa12321afd"
输出:2
解释:出现在 s 中的数字包括 [1, 2, 3] 。第二大的数字是 2 。

示例 2:

输入:s = "abc1111"
输出:-1
解释:出现在 s 中的数字只包含 [1] 。没有第二大的数字。

 

提示:

  • 1 <= s.length <= 500
  • s 只包含小写英文字母和(或)数字。

Submission

运行时间: 23 ms

内存: 16.0 MB

class Solution:
    def secondHighest(self, s: str) -> int:
        flag = False
        for i in range(9, -1, -1):
            if str(i) in s:
                if not flag:
                    flag = True
                else:
                    return i
        return -1

Explain

该题解采用的方法是从最大的数字开始向下检查每个数字是否存在于字符串中。首先,从数字9开始,逐一检查到数字0,利用Python的'in'操作符来确认数字是否出现在字符串中。在此过程中,使用一个布尔型标记变量`flag`来记录是否已经找到了第一个最大的数字。当找到第一个最大的数字时,将`flag`设置为True。如果在找到第一个最大数字后再次找到数字,则此数字即为第二大的数字,直接返回该数字。如果遍历完成后未找到两个不同的数字,则返回-1。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def secondHighest(self, s: str) -> int:
        flag = False # 用于标记是否已经找到最大的数字
        for i in range(9, -1, -1): # 从9到0逆序检查每个数字
            if str(i) in s: # 检查数字i是否在字符串s中
                if not flag: # 如果这是找到的第一个数字
                    flag = True # 标记已找到最大数字
                else: # 如果已经找到最大数字,这次找到的是第二大的
                    return i # 返回第二大的数字
        return -1 # 如果没有第二大的数字,返回-1

Explore

选择从数字9开始向下检查到0的原因是为了尽快找到最大的数字。一旦找到最大的数字,我们需要的只是第二大的数字。如果从0开始检查到9,则首先找到的较小数字并不有帮助,因为我们仍然需要继续检查更大的数字来确定哪个是最大和第二大的数字。从9到0的检查方式使得一旦找到最大数字后,下一个找到的数字即为第二大的,这样可以提高效率并简化逻辑。

除了使用`flag`标记外,还可以使用一个列表来存储已找到的数字,列表最多存储两个元素,分别为最大和第二大的数字。每当找到一个新数字时,可以将其与列表中的数字进行比较并相应地更新列表,确保列表中第一个元素始终是最大的,第二个元素是第二大的。这种方法可以更直观地跟踪最大和第二大的数字,但可能稍微增加代码的复杂性。

使用`in`操作符来检查数字是否存在于字符串中可能在字符串很长时效率较低,因为每次检查都需要遍历整个字符串。一个更高效的方法是扫描字符串一次,使用一个布尔数组记录哪些数字出现过,数组的索引代表数字,值为布尔类型表示该数字是否出现过。这样,只需遍历一次字符串和一次布尔数组即可找出最大和第二大数字,从而提高效率。

如果数字在字符串中的分布非常不均匀,特别是如果数字集中在末尾出现,使用`in`操作符的方法在检查到最后才可能找到需要的数字,这意味着每次检查都几乎需要遍历整个字符串。这在效率上是一个劣势。然而,如果使用之前提到的扫描一次字符串的方法,则数字分布的不均匀性不会影响效率,因为无论数字如何分布,都只需要遍历一次字符串,这是一个明显的优势。