leetcode 第1985道题 找出数组中第K大整数

题目详细描述如下:

给你一个字符串数组 nums 和一个整数 k 。nums 中的每个字符串都表示一个不含前导零的整数。

返回 nums 中表示第 k 大整数的字符串。

注意:重复的数字在统计时会视为不同元素考虑。例如,如果 nums 是 ["1","2","2"],那么 "2" 是最大的整数,"2" 是第二大的整数,"1" 是第三大的整数。

示例 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"

提示:

  • 1 <= k <= nums.length <= 104
  • 1 <= nums[i].length <= 100
  • nums[i] 仅由数字组成
  • nums[i] 不含任何前导零

下面介绍解题思路:

1.  注意下面的提示,1 <= nums[i].length <= 100,数字最长达到了100,因此转成整形再比较是不行的。只能从直接比较字符串上下功夫。

2. 由于各个字符串的前导非0,字符串长度又不一样,直接使用string类重载的比较函数是不行的,因此需要自己写比较函数。

下面给出了比较一种解法:

class Solution {


public:

	string kthLargestNumber(vector<string>& nums, int k) {
		std::sort(nums.begin(), nums.end(), [](const string& a, const string& b)
	{
		if (a.size() != b.size())
		{
			return a.size() < b.size();
		}
		else
		{
			return a < b;
		}
	});
		return nums[nums.size() - k];
	}
};

这种写法比较简单,sort函数的比较参数直接使用了lamda表达式,行数也很好,运行结果183ms。

对于不愿使用lamda表达式的同学来讲,看着代码怪怪的,那么来写一个不用lamda表达式的例子。如果不用lamda表达式得需要写一个仿函数,就是结构体里面只有一个重载()的函数。解法如下:

class Solution {

	struct MyComparison {
		bool operator()(const string& a, const string& b)
		{
			if (a.size() != b.size())
			{
				return a.size() < b.size();
			}
			else
			{
				return a < b;
			}
		}
	};


public:
	string kthLargestNumber(vector<string>& nums, int k) {
		std::sort(nums.begin(), nums.end(), MyComparison());
		return nums[nums.size() - k];
	}
};

这段代码中的 结构体 MyComparison 就是一个仿函数,结构体里面只有一个重载了括号的函数。

运行结果201ms。

下面对这道题进行拓展,由于提示中有 1 <= k <= nums.length <= 104,数组最大长度才104,直接采用排序是OK的。假如nums.length 是1万,10万,这种对数组的所有制排序的方法就不OK了。此时可以用优先队列来解决这种问题。

优先队列 std::priority_queue ,是一种采用堆包装的数据结构,其用法比std::sort 函数还要稍微复杂一些。由于我们无法采用string自带的重载函数,按照priority_queue的要求我们需要再string的基础上重新包装出一个数据结构,再这个重新包装的数据结构中重载()符号,code 如下:

class Solution {

	struct MyComparison {

	bool ComparStr(const string& a, const string& b)
	{
		if (a.size() != b.size())
		{
			return a.size() > b.size(); //这里要建小顶堆所以采用 > 
		}
		else
		{
			return a > b; //这里要建小顶堆所以采用 >
		}
	}



	struct MyString {
		bool operator()(const MyString& a, const MyString& b) //注意这里面是比较新建的结构体
		{
			if (a.s.size() != b.s.size())
			{
				return a.s.size() > b.s.size();
			}
			else
			{
				return a.s > b.s;
			}
		}
		std::string s;
	};


public:
	string kthLargestNumber(vector<string>& nums, int k) {
		std::priority_queue <MyString,vector<MyString>,MyString> pq; //这种方法要记牢
		for (const auto& num : nums)
		{
			if (pq.size() < k) //如果优先队列小于k,则构造新的数据结构插入队列
			{
				MyString ms;
				ms.s = num;
				pq.push(ms);
				continue; //跳过进行下一次循环
			}
			string top = pq.top().s; // 取出堆顶元素
			if (ComparStr(num, top)) //如果新遍历的string比堆顶元素要大,弹出堆顶元素,然后构建一个新的数据结构,插入优先队列,push函数内部会维护堆的完整性的操作。
			{
				MyString ms;
				ms.s = num;
				pq.pop();
				pq.push(ms);
			}
		}
		return pq.top().s;
		//std::sort(nums.begin(), nums.end(), MyComparison());
		//return nums[nums.size() - k];
	}
};

 这种优化后的解法的结果: 202ms。虽然没有更快,主要是由于数据规模太小的缘故,有点杀鸡用了宰牛刀的感觉,相信随着规模的增加 复杂度由 nlog(n)--> n的威力会显现出来。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值