九度OJ——1384

来源:互联网 发布:留学低龄化数据 编辑:程序博客网 时间:2024/04/30 11:23

最近在看《C++大学教程》和《剑指offer》,但仅仅是看代码,没有实际coding。鉴于coding是要动手实践的,因此开始要练习了。所以就从九度OJ上的“剑指offer”部分开始练习。第一题1348,找出二维数组中的数。代码其实很简单,但是前前后后折腾了一整天。下面就自己解析一下代码吧,其实核心就是书上的。但还是来总结一下吧,后面做的每道题争取都能总结一下。


最后AC的代码如下:


#include<iostream>#include <cstdio>#include <cstdlib>using namespace std;#define MAX 1002001bool find(int *matrix, int rows, int cols, int t){bool found = false;int row = 0;int col = cols - 1;if(matrix != NULL && rows > 0 && cols > 0){while(row < rows && col >= 0){if(matrix[row * cols + col] == t){found = true;break;}else if(matrix[row * cols + col] > t)col--;else row ++;}}return found;}int main(){int rows;int cols;int t;bool found = false;static int array[MAX] = {0};//int array[MAX] = {0};             //while(cin >> rows)while(scanf("%d", &rows) != EOF){//cin >> cols >> t;scanf("%d%d", &cols, &t);for(int i=0; i<rows; i++) //初始化数组for(int j=0; j<cols; j++)//cin >> array[i * cols + j];scanf("%d", &array[i * cols + j]);  found = find(array, rows, cols, t);if(found == true)//cout << "Yes\n";printf("Yes\n");else //cout << "No\n";printf("No\n");}return 0;}



其实很多时间都是花在输入输出上,因为主要部分就是书上的代码,也没有创新。因为想以后就用C++,所以想保持一下代码的C++风格,即输入输出用cin和cout。但是这样会超时。最后在大钊的点拨下,将此改为scanf和printf后,解决了“超时”的问题。这样,提交之后还是错误的原因却是我没有注意到“Yes/No”的大小写问题,囧!第一次做OJ,完全没有经验。

其实C++是不提倡使用scanf和printf的,主要原因是C++提供了流运算符>>/<<,而且能输出对象,scanf和printf是不能的。当然还有其它原因:

(引自C++为什么不提倡使用scanf和printf函数)

int printf( char *, ...);int scanf( char *, ...);

我们看到,除了第一个参数要求是char *以外,其余参数的类型不限,个数也不限。从这一点能够看出,C语言对函数参数的数据类型是不做严格的检查的,但是C++语言却是要做严格的类型检查的,这与C++支持函数重载有关。

再者,在一个程序里,如果cincoutscanfprintf混合使用,系统不能保证他们的执行次序是正确的,假如我们希望输出‘我吃’,也许输出的是‘吃我’。尽管C++提供了解决这个问题的途径,但是一般不提倡这样做。

那怎么写代码能做到测试用例的无限次输入和判断文件结尾(EOF)呢?C++中是这样:while(cin >> variable),非常简洁!当输入一个int型数时,由cin传到intvariable,循环条件成立,于是转到循环体中执行。之后若循环体执行完,再来判断条件是否成立,若此时遇到文件结尾,则由于不是int型,而发生错误,于是条件不成立,即退出循环。

而用scanf时,则是while(scanf("%d", &rows) != EOF),即要将scanf的返回值与EOF比较,其实EOF就是-1。我们可能会感到奇怪,为什么scanf会有返回值,平时调用scanf和printf时,不是直接调用的吗?其实它们都是返回int型变量的函数,如上面所引用的。

int a, b;int num, n;num = scanf("%d%d",&a, &b);n = printf("=========\n");printf("%d\n%d", num, n);


如上述代码运行后,输出为:

=========

2

10


即scanf返回的是成功读入变量的个数,而printf则返回的是它打印出的字符数。因此在while循环条件中,先输入一个变量,scanf返回1,与EOF(-1)不等,于是,进入循环体。最后当遇到EOF时,返回-1。于是就退出循环。


九度OJ可能对C++的支持不好,所以我们要写出如此风格不一致的代码,实在是难受!


再有就是可以先定义出一个最大容量的数组,然后再去初始化,但这就会占据更多的内存。如果用new/delete的话,则是用时间来换空间。需要说明的是,用static声明的数组是存储在堆中,否则是存在栈中。在本题中,如果不用static来声明的话,在VS2012中会出现stack flow的错误。但是提交到OJ上去,是能AC的!只不过有3个测试用例的时间都会比加static的时间要长。


不加static:

加了static:



我在九度OJ的论坛上,还看到了很多暴力解法,我觉得这是很好的,因为他们观察题目很仔细,也很灵活。我可能是因为直接就根据书上所说的,也没有过多地去考虑,所以就生搬硬套了!因为此题是有缺陷的,所以可以直接边输入数组的值,边进行判断,是可以达到解题的目的的。当然书上要考察的点不是这样。


最后,总结一下:

1.第一次做OJ,主要是在输入输出的问题花费了较多时间,不过也弄懂了怎么分别用cin/scanf来表示文件结束,也掌握了九度OJ的解题流程。后面加油了!

2.输出一定要和题目所要求的一致。


0 0
原创粉丝点击