有道笔试过了两天了,我其实当时就想着写篇文章好好反省下。这个编程题一道题都没AC,如果我要归咎责任,掩人耳目,保留面子,那么我会说第一道题把我卡住了,而且第一题的样例有误。但是诚实地说,是我的编程方法不对。
编程,你一定要知道解决问题的算法,知道了算法之后实现是第二步。所以假若没有想到算法就编程,那么就不可能顺利AC。而编程的规则,大部分是从题目翻译。这点考验理解力和算法基础。规则,你或者说算法很重要。有了算法之后实现就容易多了。而我在有道笔试的时候,自己主观想象的算法当总数为4时,没问题。是10就完全不对。原因很简单,没去理解问题,直接以最简单的样例来拼凑规则,这样拼凑出来的算法就很多不一定了。确实,样例的最后一个一直过不了。也好在我静下心来,只为自己的一道编程题AC而努力。最后,算法算是正确,但由于时间不够了,边界条件并未处理好。下面是题目:
小明同学把1到n这n个数字按照一定的顺序放入了一个队列Q中。现在他对队列Q执行了如下程序:
while(!Q.empty()) //队列不空,执行循环 { int x=Q.front(); //取出当前队头的值x Q.pop(); //弹出当前队头 Q.push(x); //把x放入队尾 x = Q.front(); //取出这时候队头的值 printf("%d\n",x); //输出x Q.pop(); //弹出这时候的队头 }
做取出队头的值操作的时候,并不弹出当前队头。
小明同学发现,这段程序恰好按顺序输出了1,2,3,...,n。现在小明想让你构造出原始的队列,你能做到吗?[注:原题样例第三行5有错,应该为3,以下已修正]
输入描述:
第一行一个整数T(T ≤ 100)表示数据组数,每组数据输入一个数n(1 ≤ n ≤ 100000),输入的所有n之和不超过200000。
输出描述:
对于每组数据,输出一行,表示原始的队列。数字之间用一个空格隔开,不要在行末输出多余的空格.
输入例子:
4
1
2
3
10
输出例子:
1
2 1
2 1 3
8 1 6 2 10 3 7 4 9 5
我的代码如下:
#include<queue> #include<stack> #include<vector> #include<iostream> using namespace std; void PrintOrigin(int n) { queue<int>ret; queue<int>a; int p=n; ret.push(n); while(p>0) { p--; if(p>0)a.push(p); a.push(ret.back()); while(ret.size()>1) { int k=ret.front(); ret.pop(); a.push(k); } ret.pop(); if(p==0)break; while(!a.empty()) { int k=a.front(); a.pop(); ret.push(k); } } while(!a.empty()) { int k=a.front(); a.pop(); printf("%d ",k); } } int main() { int N; while(cin>>N) { while(N--) { int n; cin>>n; PrintOrigin(n); printf("\n"); } } return 0; }
这个代码提交之后,未能在规定时间内完成任务。也是我用了两个队列不停地push和pop,这样很浪费操作时间。果然,再看算法,好像只用一个动态增长的数组,只用增加元素,挪动元素即可。这样,就有了如下代码:
#include<queue> #include<stack> #include<vector> #include<iostream> using namespace std; void PrintOrigin(int n) { vector<int>ret; ret.push_back(n); int tmp=n; int i=0; if(n==1) { printf("1"); return; } tmp--; ret.push_back(tmp); tmp--; i++; if(n==2) { printf("2 1"); return; } while(tmp>=0) { if(tmp>0)ret.push_back(tmp); i++; int k=ret[0]; int p=i-1; int begin=0; while(begin<p) { ret[begin]=ret[begin+1]; begin++; } ret[i-1]=k; tmp--; } int nr=ret.size(); for(int i=nr-1;i>=0;i--) if(i==0)printf("%d",ret[i]); else printf("%d ",ret[i]); } int main() { int N; while(cin>>N) { while(N--) { int n; cin>>n; PrintOrigin(n); printf("\n"); } } return 0; }
写这篇文章的目的,一是提醒自己编程时必须已经有解法,如果没有,要继续去寻求规则。二是要注意编程的一些技巧,如边界条件和优化等。