中金所技术0922笔试第三题--近月和季月

中金所技术0922笔试第三题–近月和季月

考试的时候没有做出来,时间短没有理清楚,结束后梳理了一下代码如下,输了几个测试用例是正确的,不知道能不能过,有详细注释,有问题欢迎大家评论指正。

1.代码

#include <iostream>
#include <vector>
#include<string>
#include<set>
#include<sstream>
using namespace std;

vector<int> getdate(int y, int m, int dm) {       //求y年m月第dm个月后的年份year和月份month
	int thisyear = y + (m + dm) / 12;
	if ((m + dm) % 12 == 0) {
		thisyear -= 1;
	}
	int thismonth = (m + dm) % 12 == 0 ? 12 : (m + dm) % 12;

	return { thisyear, thismonth };
}

string getresstring(int yy, int mm) {            //根据年yy和月mm生成字符串,年份和月份少于两位数时前面补0
	string ty = yy < 10 ? "0" + to_string(yy) : to_string(yy);
	string tm = mm < 10 ? "0" + to_string(mm) : to_string(mm);
	string re = "IZ" + ty + tm;
	return re;
}

int main() {
	string str,str1;
	getline(cin, str);
	stringstream ss(str);
	vector<int> data;
	while (getline(ss, str1, ',')) {    //输入按‘,’分词
		data.emplace_back(stoi(str1));
	}
	int m = data[0], n = data[1], year = data[2] / 100, month = data[2] % 100, dis = data[3];    //m:近月数,n:季月数,year:开始年份,month:开始月份, dis:未来月数
	
	set<string> jin, ji;        //jin:近月字符串集合, ji:季月字符串集合

	vector<string> thisrow;

	string lastmonth = "";     //记录上个月的字符串,用于集合删除操作
	int ptr = 0;
	for (int i = 0; i < dis; i++) {        //遍历未来月数dis中的每一月
		auto date = getdate(year, month, i);
		int thisyear = date[0];
		int thismonth = date[1];
		
		thisrow= vector<string>();         //记录该月新增字符串

		if (i == 0) {						//第一个月直接遍历窗口大小m中的月份
			for (int j = 0; j < m; j++) {
				auto date1 = getdate(thisyear, thismonth, j);
				string re1 = getresstring(date1[0], date1[1]);
				thisrow.emplace_back(re1);
				jin.insert(re1);
			}
		}
		else {                             //以后只考虑窗口下一个月份
			if (m == 0) continue;          //m==0的情况不进入
			auto date2= getdate(thisyear, thismonth, m-1);
			string re2 = getresstring(date2[0], date2[1]);
			if (!jin.count(re2) && !ji.count(re2)) {   //如果当前月是新的月份,且不在季月中,则为新增
				thisrow.emplace_back(re2);
			}
			
			if (ji.count(re2)) {                     //如果当前月在季月集合中,则将该字符串从季月中删除,改成近月字符串
				ji.erase(re2);
			}
			jin.insert(re2);
			jin.erase(lastmonth);                   //从jin集合中删去上个月的近月字符串
		}

		lastmonth = getresstring(thisyear, thismonth);

		while (ji.size() < n) {                     //判断当前季月字符串集合大小是否达到n个,如果没有,则需利用ptr往后遍历找到符合情况的季月加入到集合中
			auto date3= getdate(year, month, ptr);
			
			ptr++;                                  //ptr为全局变量,表示从开始年份year月份month的第ptr个月后
			if (date3[1] != 3 && date3[1] != 6 && date3[1] != 9 && date3[1] != 12) {             //不为季月直接不考虑
				continue;
			}
			string strt = getresstring(date3[0], date3[1]); 
			if (jin.count(strt)) {                       //已经被标记为近月,也不考虑
				continue;
			}
			ji.insert(strt);                            //符合条件,为季月,插入到季月集合以及新增
			thisrow.emplace_back(strt);
		}
		
		for (int i = 0; i < thisrow.size(); i++) {      //打印结果
			if (i == 0) {
				cout << thisrow[i];
			}
			else {
				cout << "," << thisrow[i];
			}
		}
		cout << endl;
	}
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值