1985. 找出数组中的第 K 大整数

【算法题解】字符串数组中第 k 大整数 — Python 实现详解


题目描述

给定一个字符串数组 nums,其中每个字符串都表示一个没有前导零的整数。我们需要找到其中第 k 大的整数并返回它对应的字符串。

注意:

  • nums 中的每个字符串都表示一个整数,但可能非常大(长度最多 100),无法直接转换为整数类型进行比较。
  • 重复的数字视为不同的元素,即统计第 k 大时不会去重。
  • 输入保证:1 <= k <= nums.length <= 10^41 <= nums[i].length <= 100nums[i] 只包含数字且无前导零。

题目示例

示例 1:

输入:nums = ["3","6","7","10"], k = 4
输出:"3"
解释:
nums 中的数字排序为 ["3","6","7","10"]
第 4 大整数是 "3"

示例 2:

输入:nums = ["2","21","12","1"], k = 3
输出:"2"
解释:
排序后 nums = ["1","2","12","21"]
第 3 大整数是 "2"

示例 3:

输入:nums = ["0","0"], k = 2
输出:"0"
解释:
排序后 nums = ["0","0"]
第 2 大整数是 "0"

解题分析

该题的核心难点在于:

  • 字符串数字的比较
    数字用字符串形式给出,且长度最大可达 100。
    直接将字符串转成整数比较会导致数据溢出或效率低下。
  • 正确排序规则
    字符串数字的大小比较应基于数值大小,而不是字符串的字典序(除非长度相等)。

如何比较两个字符串表示的数字大小?

  • 先比较长度:长度长的数字更大(例如,"1234" > "567")。
  • 长度相同,则逐字符比较(类似字典序),从最高位往后比较。

解题方法

Python 提供了灵活的排序方法,可以通过自定义排序键(key)实现正确的排序。

具体步骤:

  1. 定义排序键
    使用 key=lambda x: (len(x), x),即先按照数字字符串的长度升序排序,再按字典序升序排序。
    这样排序后,数组从小到大排列。
  2. 取第 k 大
    排序后,第 k 大的数字就是倒数第 k 个元素,索引为 -k
  3. 返回结果
    直接返回倒数第 k 个元素即可。

代码实现(Python)

from typing import List

class Solution:
    def kthLargestNumber(self, nums: List[str], k: int) -> str:
        # 按数字大小升序排序
        nums.sort(key=lambda x: (len(x), x))
        # 返回倒数第 k 个元素,即第 k 大数字
        return nums[-k]

代码解析

  • nums.sort(key=lambda x: (len(x), x))
    对字符串先按长度排序,再按字典序排序,保证整体按数字大小升序。
  • return nums[-k]
    列表已经升序排序,倒数第 k 个即为第 k 大数字。

时间复杂度分析

  • 排序的时间复杂度为 O(N log N * M)
    其中 N 是数组长度,M 是最大字符串长度(比较两个字符串最多比较 M 位)。
  • 由于 M 最大为 100,且 N 最大为 10^4,算法在现实中运行效率足够。

示例说明

以示例 2 为例:

nums = ["2", "21", "12", "1"]
k = 3
  • 排序后,nums 变成 ["1", "2", "12", "21"]
    按数字大小升序排列。
  • 第 3 大数字是倒数第 3 个,即索引 -3 的元素 "2"

思路比较与总结

方法

优点

缺点

转整数比较

简单直观

数据大时会溢出

自定义比较

适用所有长度数字,灵活

代码稍复杂,需保证比较正确

预处理排序

利用内置排序快速,代码简洁

依赖排序稳定和正确的 key

本题最优方案是利用 Python 的排序稳定性和灵活的排序键,实现基于长度和字典序的排序,保证高效准确。


总结

  • 本题的关键是正确比较字符串表示的大整数。
  • 通过先比较长度,再字典序比较,能够实现数字大小排序。
  • 利用内置排序和合适的排序键,可以轻松得到第 k 大数字。
  • 此方法不仅高效,而且代码简洁,适合面试和实际编程使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值