【牛客题解】 --发邮件错排问题

1、题目描述

NowCoder每天要给很多人发邮件。有一天他发现发错了邮件,把发给A的邮件发给了B,把发给B的邮件发给了A。于是他就思考,要给n个人发邮件,在每个人仅收到1封邮件的情况下,有多少种情况是所有人都收到了错误的邮件?
即没有人收到属于自己的邮件。

他给的测试用例和输入输出描述是这样的:
在这里插入图片描述我说这道题是典型的动态规划,没人反驳吧。

题解

n个邮件放入n个邮箱,我们用D(n)表示,那么D(n-1)的意思就是说n-1个邮件放入n-1个邮箱

  • 第一步:我们将第n个邮件,放入一个邮箱,那么共有n-1种情况,假设他放入了第k个邮箱
  • 第二步:放入第k个邮箱后,那就有两种情况:1、k邮箱所对应的第k号邮件,也恰好放入了第一步里面第n个邮件所对应的n号邮箱,那剩下的n-2个元素就是有D(n-2)种方法  2、k邮箱的邮件并没有放入第n个邮箱,那就是剩下的n-1个元素就有D(n-1)种方法。

    特殊的,我们还知道D(1)=0,D(2)=1;
    那我们的递推方程就出来了:D(n)=(n-1)*[D(n-1)+D(n-2)]

C++代码

前括弧  代码真的好简短  后括弧

#include <iostream>
#include <stdlib.h>
using namespace std; 
int main()
{
	long long res[21] = { 0,0,1 };
	for (int i = 3; i < 21; i++)
	{
		res[i] = (i - 1)*(res[i - 1] + res[i - 2]);
	}
	int n;
	while (cin >> n)
	{
		cout << res[n] << endl;
	}
	system("pause");
	return 0;
}

2、题目描述

广场上站着一支队伍,她们是来自全国各地的扭秧歌代表队,现在有她们的身高数据,请你帮忙找出身高依次递增的子序列。 例如队伍的身高数据是(1、7、3、5、9、4、8),其中依次递增的子序列有(1、7),(1、3、5、9),(1、3、4、8)等,其中最长的长度为4。

咱再来看下测试用例的输入输出 :
在这里插入图片描述
我先说哈,我的代码在VS上跑过了,在牛客上没跑过,时间复杂度太大了,循环太多超时了,所以先放在这,等我学的好点了再来改进。

我的思路:先以第一个数为基准,max记录他的下标,从他往后找第一个比他大的数,max记录他的下标并把该数写入数组,一直找到结束。在进行找第二个比他大的数,max记录下标一直到结束。这一轮结束后,在以第二个数为基准,找比他大的数,依次类推。

代码:

//时间复杂度太大了,最后强调一遍
int TheMaxLength(vector<int> a)  
{
	int max = 0;
	vector<int> ret;
	for (int i = 0; i < a.size(); i++)
	{
		int max1 = i;
		for (int j = i + 1; j < a.size(); j++)
		{
			ret.push_back(a[i]);
			if (a[j] > a[i])
			{
				max1 = j;
				ret.push_back(a[j]);
			}
			for (int k = max1+1; k < a.size(); k++)
			{
				if (a[k] > a[max1])
				{
					max1 = k;
					ret.push_back(a[k]);
				}
			}
			if (ret.size() > max)
				max = ret.size();
			ret.clear();
		}
	}
	return max;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值