2021年面试题——数数问题

作者:小 琛
欢迎转载,请标明出处

该博文讲述2021年美团春招原题,数数

题目描述:

小美正在统计她公司的数据。她想要知道一定时间段内的某种特征。因此,她将n条数据按时间排好序依次给出,想要知道以某条数据开始的一个连续数据段内数据的众数情况。
形式化地,始出n个数a1…an分别表示时刻1,2…-.n的数据值。小美想要知道连读X条数据的情况,即a… +K-1。请你求出当i=1,2.n-K+1时,aL…3+K-1这些数据中的"众数"。如果"众数"有多个,输出最小的那一个.
注意,此处“众数的定义与通常定义有些许区别。我们这样定义“众数”:如果出现次数最多的数只有一个数,那么“众数”就是它:否则,众数为出现次数最多的数中,数值最小的那一个。
例如,序列[123 3]中,3出现了两次,其他数仅出现了一次,所以“众数为3.
序列[123]中,三个数出现次数都为1次,都是出现次数最多的数(不存在出现次数大于1的数),所以“众数”是其中的数值最小的1.
序列[5252334]中.5、2、3均出现了2次,都是出现次数最多的数(不存在出现次数大于2的数),所以“众数”是其中的数值最小的2。

输入:n代表数据总数,k代表长度,vector存放输入的若干个数
输出:从i=0开始的n-k+1个数据。每个数据代表从i下标开始,该k个数的众数

题目解析:

该题目的第一个难点就是,题意生涩难懂,不容易将问题转化。
实际上,问题就是,给若干个数,再给定一个长度k,k满足小于长度n,要求数据内从i=0开始向后k个数据的众数,因此该组数据内共应有n-k+1个
如下图,k给定后,相当于一个滑动窗口,窗口向前滑动,对于这若干个数据,求里面包含的众数在这里插入图片描述

题目解答:

该题解法很多,例如取出后排序,再寻找。但这些方法的时间复杂度和空间复杂度都无法保证,因此正解应当为动态规划。

  1. 确定问题:求k个数据中的众数
  2. 举例帮助分析:arr[]={5,1,2,2,3,5};n=6,k=3
  3. 寻找状态关系:窗口长度为k时的众数,等于窗口长度为k-1处的众数和arr[k-1]数量加一的最大值,若相同则为arr[k-1]和k-1处众数的最小值
  4. 动态转移方程:dp(i,j)=max(mp[arr[j-1]], ++mp[arr[j]])。当二者不相等时.其中mp为记录使用的哈希表。
  5. 初始状态,k=1时,dp[i][j]=arr[j]
  6. 记录法记录每个状态。
    在这里插入图片描述
    注意:这里的对于dp数组的填充,必须满足按行填写,且保证每行填写完成后将哈希表清空

代码:

vector<int> GetNum(vector<int> vec, int size, int k)
{
	vector<int> res(size - k + 1);
	vector<vector<int>> dp(size, vector<int>(size));
	map<int, int> mp;
	for (int i = 0; i < size - 1; i++)
	{
		mp.clear();
		dp[i][i] = vec[i];
		mp[vec[i]]++;
		for (int j = i + 1; j < size; j++)
		{
			mp[vec[j]]++;
			if (mp[dp[i][j - 1]] != mp[vec[j]])
				dp[i][j] = mp[dp[i][j - 1]]> mp[vec[j]] ? dp[i][j-1] : vec[j];
			else
				dp[i][j] = min(dp[i][j - 1], vec[j]);
		}
	}
	for (int i = 0, j = k - 1; i < size - k + 1; i++, j++)
	{
		res[i] = dp[i][j];
	}
	return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值