D a t e : 2022 − 10 − 02 \color{FF6699}{Date:2022-10-02} Date:2022−10−02
I
f
\color{FF6699}{If}
If
I
\color{FF6699}{I}
I
c
a
n
′
t
\color{FF6699}{can't}
can′t
I
\color{FF6699}{I}
I
m
u
s
t
;
\color{FF6699}{must;}
must;
I
f
\color{FF6699}{If}
If
I
\color{FF6699}{I}
I
m
u
s
t
\color{FF6699}{must}
must
I
\color{FF6699}{I}
I
c
a
n
!
\color{FF6699}{can!}
can!
文章目录
🍎1. 成绩统计🍎1
🍇题目🍇
编写一个程序,建立了一条单向链表,每个结点包含姓名、学号、英语成绩、数学成绩和C++成绩,并通过链表操作平均最高的学生和平均分最低的学生并且输出。
输入格式
输入n+1行,第一行输入一个正整数n,表示学生数量;接下来的n行每行输入5个数据,分别表示姓名、学号、英语成绩、数学成绩和C++成绩。注意成绩有可能会有小数。
输出格式
输出两行,第一行输出平均成绩最高的学生姓名。第二行输出平均成绩最低的学生姓名。
样例输入
2
yx1 1 45 67 87
yx2 2 88 90 99
🍇思路🍇
科目数量固定,所以求平均成绩最高最低相当于求总分最高最低的即可。
🍇代码🍇
void ScoreCount(int i_StudentNum)
{
if ((0 > i_StudentNum))
{
cout << "Invalid date entered." << endl;
}
Student stu[i_StudentNum];
double scoreSum = 0.0;
double minSum = 300.0;
double maxSum = 0.0;
string minName = "";
string maxName = "";
for (int i = 0; i < i_StudentNum; i++)
{
cout << "Please input Student [" << i <<"]'s name, id, english score, math score, cplusplus score: " << endl;
cin >> stu[i].name >> stu[i].id >> stu[i].english >> stu[i].math >> stu[i].cplusplus;
scoreSum = stu[i].math + stu[i].english + stu[i].cplusplus;
if (minSum > scoreSum)
{
minSum = scoreSum;
minName = stu[i].name;
}
if (maxSum < scoreSum)
{
maxSum = scoreSum;
maxName = stu[i].name;
}
}
cout << "The person with the lowest average score is [" << minName << "]." << endl;
cout << "The person with the highest average score is [" << maxName << "]." << endl;
}
🍊2. 星系炸弹🍊
🍌题目🍌
在X星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。
每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸。
有一个贝塔炸弹,2014年11月9日放置,定时为1000天,请你计算它爆炸的准确日期。
🍌思路🍌
炸弹会在定时达到那天爆炸,也就是当定时时间从N减到0时的那天就是爆炸的准确日期,那么本题只需要通过递减定时时间的同时,计算新的日期即可,要注意的是
- 每个月的最后一天时,新增一天,应该将月份增1,日数重置为1
- 2月份的准确天数要先判断当前年份是闰年还是平年
🍌代码🍌
int GalaxyBomb(int i_Year, int i_Mon, int i_Day, int i_Timing)
{
if (!IsValidDate(i_Year, i_Mon, i_Day))
{
return -1;
}
int curYear = i_Year;
int curMon = i_Mon;
int curDay = i_Day;
while (i_Timing)
{
bool IsSpecialDay = false;
if (2 == curMon)
{
if (IsLeapYear(curYear))
{
if (29 == curDay)
{
curDay = 1;
curMon++;
IsSpecialDay = true;
}
}
else
{
if (28 == curDay)
{
curDay = 1;
curMon++;
IsSpecialDay = true;
}
}
}
else if (sBigMonth(curMon))
{
if (12 == curMon)
{
if (31 == curDay)
{
curDay = 1;
curMon = 1;
curYear++;
IsSpecialDay = true;
}
}
if (31 == curDay)
{
curDay = 1;
curMon++;
IsSpecialDay = true;
}
}
else
{
if (30 == curDay)
{
curDay = 1;
curMon++;
IsSpecialDay = true;
}
}
if (!IsSpecialDay)
{
curDay++;
}
i_Timing--;
}
char strDate[100];
memset(strDate, 0, 100);
sprintf(strDate, "The bomb will explode on %d-%d-%d", curYear, curMon, curDay);
cout << strDate << endl;
return 1;
}
🍍3. 特别数的和🍍
🥭题目🥭
小明对数位中含有 2、0、1、9 的数字很感兴趣(不包括前导 0),在 1 到 40 中这样的数包括 1、2、9、10 至 32、39 和 40,共 28 个,他们的和是 574。
请问,在 1 到 n 中,所有这样的数的和是多少?
输入格式
共一行,包含一个整数 n。
输出格式
共一行,包含一个整数,表示满足条件的数的和。
🥭思路🥭
只需要遍历从1到N的所有数字,如果该数字中包含[2, 0, 1, 9]就进行相加即可
🥭代码🥭
int SumOfSpecialNum(int i_Inter)
{
if ((0 > i_Inter) || (10000 < i_Inter))
{
return -1;
}
int o_sum = 0;
for (int i = 1; i <= i_Inter; i++)
{
int j = i;
while (j)
{
int tmp = j % 10;
if ((2 == tmp) || (0 == tmp) || (1 == tmp) || (9 == tmp))
{
cout << i << endl;
o_sum += i;
break;
}
j /= 10;
}
}
return o_sum;
}
🍒4. 蛇形填数🍒
🍑题目🍑
1 | 2 | 6 | 7 | 15 | … |
---|---|---|---|---|---|
3 | 5 | 8 | 14 | … | |
4 | 9 | 13 | … | ||
10 | 12 | … | |||
11 | … | ||||
… | |||||
蛇形矩阵如上,容易看出矩阵第二行第二列中的数是5。请你计算矩阵中第20 行第20 列的数是多少? |
🍑思路🍑
蛇形矩阵的规律就是碰到边界就往回走,那么本题实际只需要做好边界判定的逻辑即可
- 当碰到上边界时,往左下方向走
- 当碰到左边界时,往右上方向走
- 遍历到要求的位置时停下即可
🍑代码🍑
int SnakeMatrix(int i_X, int i_Y)
{
if ((0 >= i_X) || (0 >= i_Y))
{
return -1;
}
int MatrixLen = (i_X > i_Y) ? ((i_X * 2) - 1) : ((i_Y * 2) - 1);
int MatrixItemStart = 1;
int i = 0;
int j = 0;
bool Process = false;
vector<vector<int> > Matrix(MatrixLen, vector<int>(MatrixLen, 0));
Matrix[0][0] = MatrixItemStart++;
while (1)
{
if (0 != Matrix[i_X - 1][i_Y - 1])
{
break;
}
j++;
while (-1 != j)
{
Matrix[i][j] = MatrixItemStart++;
if (0 == j)
{
break;
}
i++;
j--;
}
i++;
while (-1 != i)
{
Matrix[i][j] = MatrixItemStart++;
if (0 == i)
{
break;
}
i--;
j++;
}
}
return Matrix[i_X - 1][i_Y - 1];
}
🍋5. 日志统计🍋
🍉题目🍉
小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 N 行。
其中每一行的格式是:
ts id
表示在 ts 时刻编号 id 的帖子收到一个”赞”。
现在小明想统计有哪些帖子曾经是”热帖”。
如果一个帖子曾在任意一个长度为 D 的时间段内收到不少于 K 个赞,小明就认为这个帖子曾是”热帖”。
具体来说,如果存在某个时刻 T 满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是”热帖”。
给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。
输入格式
第一行包含三个整数 N,D,K。
以下 N 行每行一条日志,包含两个整数 ts 和 id。
输出格式
按从小到大的顺序输出热帖 id。
每个 id 占一行。
输入样例:
7 10 2
0 1
0 10
10 10
10 1
9 1
100 3
100 3
输出样例:
1
3
🍉思路🍉
题目要求:升序输出所有的热帖id
那么关键点就是怎么判断是不是热帖?
存在某个时刻 T 满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是”热帖”。
这里举个例子就比如此时D = 10, K = 2
帖子a和帖子b在1时刻收到一个赞,然后帖子a在10时刻再次收到一个赞,帖子b在11时刻也收到一个赞
对于帖子a来说:在 [1, 11) 这个时间段里收到了两个赞,所以a是热帖
对于帖子b来说:在 [1, 11) 这个时间段里只有一个赞,第二个赞是在11时刻收到的,不在区间内
所以具体思路如下:
- 先获取点赞数符合条件的帖子id,同时记录下该id每一个赞对应的时间段
- 对第一步获取的热帖id的每一个赞的时刻进行排序,只要其第二个赞的时间减去第一个赞的时间符合热帖条件的id即为热帖id
- 最后对热帖id进行排序即可
🍉代码🍉
vector<int> LogStatistics(int i_Nth, int i_Dth, int i_Praisenum)
{
vector<int> result = {-1};
if ((1 > i_Nth || 100000 < i_Nth)
|| (1 > i_Dth || 10000 < i_Dth)
|| (1 > i_Praisenum || 100000 < i_Praisenum))
{
return result;
}
vector<int> IsValidId; // 记录符合条件的ID
vector<int> IdFrequency(200, 0); // 记录每个ID出现的次数
vector<vector<int> > IdEveryTime(200, vector<int>(200, 0)); // 记录每个ID每次出现的时间,行为 id, 列为 ts
for (int i = 0; i < i_Nth; i++)
{
int ts = 0;
int id = 0;
cout << "Please input [" << i << "]'s ts id: ";
cin >> ts >> id;
IdFrequency[id]++;
if (i_Praisenum == IdFrequency[id])
{
IsValidId.push_back(id);
}
IdEveryTime[id][IdFrequency[id]] = ts;
}
sort(IsValidId.begin() + 1, IsValidId.end());
for (int i = 0; i < IsValidId.size(); i++)
{
vector<int> IdTime; // 记录每个 id 出现的时间
for (int j = 1; j <= IdFrequency[IsValidId[i]]; j++)
{
IdTime.push_back(IdEveryTime[IsValidId[i]][j]);
}
sort(IdTime.begin(), IdTime.end());
if (i_Dth > (IdTime[i_Praisenum - 1] - IdTime[0]))
{
result.push_back(IsValidId[i]);
}
}
sort(result.begin(), result.end());
return result;
}