目录ios
题目:面试
分析:数组
C++ STL代码:数据结构
总结:函数
来自湖大程序设计训练系统(外网进不去,因此不贴连接了)。测试
问题描述 | 在咱们先在使用的日历中,闰年被定义为能被4整除的年份,可是能被100整除而不能被400整除的年是例外,他们不是闰年。例如:1700,1800,1900和2100年不是闰年,而1600,2000和2400是闰年。给定从公元2000年1月1日开始逝去的天数,你的任务是给出这一天是哪年哪月哪日星期几 |
输入数据 | 输入包含若干行,每行包含一个正整数,表示从2000年1月1日开始逝去的天数。输入最后最后一行是-1,没必要处理。能够假设结果的年份不会超过9999. |
输出要求 | 对每一个测试样例,输出一行,该行包含对应的日期和星期几。合适为“YYYY-MM-DD DayOfWeek”。其中“DayOfWeek”必须是下面中的一个:“Monday”,“Tuesday”,“Wednesday”,“Thursday,“Friday”,“Saturday”,“Sunday”。优化 |
输入样例 | 1730 -1设计 |
输出样例 | 2004-09-26 Sunday 2004-10-06 Wednesday 2004-10-16 Saturday 2004-10-16 Sunday |
首先这道题看着很复杂,由于涉及闰年和平年天数不同,闰年366天,2月为29天;平年365天,2月为28天。并且每个月的天数也不相同,一、三、五、七、八、十、12月为31天,四、六、九、11月为30天,没有太大的规律可循,因此不能用 逝去的天数 取余一年的天数 。只有星期是每星期都是7天,因此能够用 逝去的天数 取余 7来判断星期几。code
首先咱们可能想到最蠢的办法一天一天判断,每到7天星期归0,每到月末月数+1,每到12月年数+1,月数归1.但这个办法太蠢,若是7000年的话得算到啥时候。
因此咱们可能会想到先判断是哪一年,再判断是哪一月,再计算出是哪一天,最后计算是星期几。在年和月判断的时候最开始咱们多是想到用if()else语句,先判断剩余天数是否大于当前年全部天数(闰年366天,平年365天),而后再判断若是是闰年则减去366天,若是是平年则减去365天。最后剩余天数是不够一年所含天数的,因此年份算出来了。一样能够循环判断求出所在月份。最后天数+1就能够了。
那么问题来了,咱们怎么判断年份是闰年仍是平年,怎么判断月份的天数,咱们可能想到用if()else语句来判断,那么咱们每次都要判断一下,若是咱们事先将一年中每个月所含天数用一个数组存起来的话是否是更方便判断,一样,咱们是否是也能够用数组将星期几也存进去。因此咱们选择数组存储年份所含天数,月份所含天数,星期几字符串。
最后,上面咱们是一年一年判断,而后减去年份天数(366/365),那咱们在判断一年是闰年后,咱们是否是能够确定接下来的3年都是平年,若是剩余天数够的话咱们是否是就能够直接减去3*365天。而后再判断是不是闰年。这样运行时间又能变为原来1/4。
注意:天数最后要+1;要用取余(%)判断是不是闰年;输出格式要控制好,日期格式是2000-09-01,如过剩余天数是个位数,则要在前边加上0,具体作法能够参照下面代码,C++控制数据按照指定位数输出,主要用到C++两个输出控制,setw(位数),和setfill(指定字符)。须要加上头#include <iomanip>。
cout << setw(2) << setfill('0') <<month << '-' << setw(2) << setfill('0') << day+1 << ' ' ;
#include <iostream> #include <vector> #include <iomanip> using namespace std; int main() { int yType(int y);/*判断年份是润年仍是平年的函数,返回0是平年,返回1表示是润年*/ vector<int> elapseDay;/*因为没有具体说明测试多少个,因此用动态存储vector存放逝去的天数列表*/ int monthOfY[2][13] = { {0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31} };//monthOfY[0]表示平年每个月天数,monthOfY[1]表示闰年每个月天数 char weeks[7][12] = {"Saturday","Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };/*星期字符串,2000年1月1号是周六,因此从周六开始*/ int year = 2000;/*当前年份*/ int yd[2] = {365,366};/*yd[1]表示润年,yd[0]表示平年*/ int month = 0;/*月份*/ int day = 0;/*存储逝去的天数*/ int week = 0;/*标识星期几*/ int temp;/*暂存中间变量*/ int yT = 0; /*标识平年仍是润年*/ while(1)/*从输入流读入逝去的天数*/ { cin >>temp; if(-1 == temp){ break; } elapseDay.push_back(temp);/*将temp插入到elapseDay末尾*/ } vector<int>::iterator i = elapseDay.begin();/*迭代器遍历vector*/ for( ;i != elapseDay.end(); i++)/*循环输出每一个逝去的天数对应的日期*/ { day = *i; week = day%7; /*计算星期几*/ for(year=2000; day >= yd[yT=yType(year)]; year ++)/*从2000年开始,算出当前年份,从yType()函数处可得知本年属于平年仍是润年*/ { day -= yd[yT];/*减去本年天数*/ /*day -= 365*3; year +=3; */ } for(month = 1; day >= monthOfY[yT][month]; month++)/*month对应月份,判断当前剩余天数是否大于本月所含天数,小于的话就退出for循环*/ { day -=monthOfY[yT][month]; /*day是剩余天数,每次循环减去本月天数*/ } cout << year << '-' ; cout << setw(2) << setfill('0') <<month << '-' << setw(2) << setfill('0') << day+1 << ' ' ; /*控制输出位数,保证输出格式和要求一致*/ cout << weeks[week] <<endl; } return 0; } int yType(int y)/*判断y年份是平年仍是润年*/ { if( (y%400==0) || (y%4==0 && y%100!=0) )/*若是能被400整除的话就不用判断后边的了,不然判断是不是能被4整除不能被100整除*/ { return 1;/*是润年*/ }else{ return 0;/*不是润年*/ } }
在答题的过程当中要仔细阅读题目,首先分析可使用什么数据结构来存题目中出现的数据,而后再分析此种数据结构是否可行,不行的话换个数据结构。就这样What(用什么数据结构),Why(为何用这种数据结构,有什么好处)不断重复优化。这些在写公司面试题或者要求时间空间效率的时候是比较好的方法。在作CCF-CSP考试前两题的时候估计几乎不怎么用,只要把题作出来,能得满分就行,对于代码风格,时间空间效率只要知足条件就行,要求不太苛刻。
题目中充分利用了数组,很多题目均可以很巧妙的应用数组,好比CCF-CSP2013-12-1这道题,详见稍后再写。