Day10 2023/03/09
难度:简单
题目
有一个整型偶数n(2<=n<=10000),你要做的是:先把1到中的所有奇数从小到大输出,再把所有的偶数从小到大输出。
- 输入:第一行有一个整数i(2<=i<30)表示有i组测试数据:每组有一个整型偶数n。
- 输出:第一行输出所有的奇数。第二行输出所有的偶数
示例1
输入: 1 10
输出: 1 3 5 7 9
2 4 6 8 10
说明: 输入中第一个数代表测试1行数据,第二个数代表整型偶数10,
输出第一行为所有奇数,第二行为所有偶数
运行实例
思路
本题核心是如何判断奇偶数,通过对2取余即可(j%2),如果余数为0,则为偶数,否则为奇数。这个我相信大家都知道,没什么可细讲的。下面说一下本题在代码实现上的一些巧思 (重点!!!) 😎
-
本题要求的是第一行输出奇数,第二行输出偶数。这个问题看似简单,但是实际用代码实现这个隔行输出的效果,我相信大多数同学的做法无非下面两种!
-
第一种简单暴力,但是所占用的时间和空间是最高的,直接三个并行的for循环来实现(我丢~😐),第一个for循环实现判断奇偶数,并把奇偶数各自添加到一个数组中存储下来,然后再用两个for循环各自遍历数组打印奇数和偶数来实现隔行打印的效果。
-
第二种仅比第一种少一个for循环,时间上稍好一些,使用两个并行的for循环,第一个for循环判断奇数并直接打印同时把偶数也添加到一个数组中(这样空间上还少使用一个数组存储奇数!),第二个for循环遍历偶数数组并打印。
既然说了前两种实现的不足,那自然是有解决办法的,本题我将采用仅使用一个for循环并且一个数组都不需要,使用字符串就可以实现题目要求的效果,具体实现如下:
- 在第二种方法的基础上,撤去存储偶数的数组,改用辅助字符串的方式。
- 通过一个for循环判断奇偶数的同时,打印奇数并把偶数累加到辅助字符串中 (神之一手!!!)
- for循环结束,奇数已经打印完毕,接着直接打印字符串(即偶数打印完毕),这样就实现了隔行打印的效果,并且也无需数组存储。
关键点
- 用过哈希法的同学都知道这是一种非常好用的空间换时间的方法(典型特征:通过使用辅助的哈希表或者数组等其他辅助容器),本题同理,只是使用的是辅助字符串,而不是常见的数组,当然空间上字符串是优于数组的。
算法实现
c++代码实现-奇偶数分离
#include <iostream>
#include <string>
using namespace std;
// 奇偶数分离
int main() {
int i = 0, n = 0; // 有i组测试数据 n为每组数据的整型偶数
cin >> i; // 输入i值
while (i-- && cin >> n) {
if(n % 2 != 0) return 0; // 题目要求n为整型偶数
string str = ""; // 辅助字符串
for (int j = 1; j <= n; j++) { // 循环判断1到n之间的奇数和偶数
if(j % 2 != 0) cout << j << ' '; // 打印奇数
else str+= to_string(j) + ' '; // 获取偶数
}
cout << endl << str; // 打印偶数
}
return 0;
}
- 时间复杂度 --- 不考虑输入数据所占用的时间,仅需要一个for循环需要执行n次,其中n为整型偶数
- 空间复杂度 --- 使用辅助字符串大小为n/2,其中n为整型偶数
总结
本题不禁让我们深思,即使是一些简单的题目,当解法的比较固定的时候(即代码上虽有差异,但实现的核心思想大差不差的时候),我们是否可以通过更深一步的 优化代码,不仅实现从感官上降低冗余,让代码看起来更加的简洁,还能进一步达到更优的时间和空间占有率(由于代码优化的程度不同,即使时间和空间复杂度相同的代码,在具体运行的时候还是会有差异)。