【JAVA】深深跪了,OJ题目JAVA与C运行效率对比(附带清华北大OJ内存计算的对比)

看了园友的评论之后,我也好奇清橙OJ是怎么计算内存占用的。重新测试的情况附在原文后边。

-------------------------------------- 这是切割线 --------------------------------------------

最近自学Java,试着用Java刷几道OJ的题来熟悉基本语法。

起初几道简单题,没太留意程序的执行效率。今天做了一道简单的递归题,竟然运行超时了!由于本人算法方面功底太差,不懂的如何优化,想了个投机的办法应付了过去。但又觉得不可思议,照以前用C语言刷OJ的经验,不可能这种规模的数据就运行超时。于是我将代码从eclipse复制黏贴到VC中,改成C程序,重新测试,结果惊人。

以下是详细情况:

一、题目

题目位于:http://oj.tsinsen.com/ViewGProblem.page?gpid=A1069

问题描述

  幻方(magic square)是一个非常有趣的矩阵,n阶的幻方表示一个n阶矩阵,它的元素恰好是1~N^2,它的各行,各列,以及对角线之和都相等。下面是一个非常经典的3阶幻方:
  2 7 6
  9 5 1
  4 3 8
  你的任务是找出字典序第K小的4阶幻方。
  这里的幻方的字典序定义为:把幻方按行优先排成一条N^2的序列后的字典序(如上面这个幻方,排成这样一条序列:2 7 6 9 5 1 4 3 8)。
  其中K<=100。
  字典序的定义为:在某一系列字符串中,首先按照第一个字符明确其先后顺序,如果第一个字符相同,则根据第二个字符的大小关系明确其先后关系。以此类推 。例如:
  1 2 3 4 5 6 7 8 9 10 11在2 1 3 4 5 6 7 8 9 10 11之前
  1 2 3 4 5 6 7 8 9 10 11在1 3 2 4 5 6 7 8 9 10 11之前
输入格式
  输入仅包含一行K。
输出格式
  4行4列的幻方,数之间用一个空格隔开,行末不要有多余的空格。
样例输入
1
样例输出
1 2 15 16
12 14 3 5
13 7 10 4
8 11 6 9
 
 
二、Java解答结果
这是我的java解(算法比较渣,风格比较丑,请多指教=。=)
  1.  Java代码
  2. import java.util.Scanner;
  3. public class Main {
  4. static boolean[] used = new boolean[17];
  5. static int k;
  6. static int[][] ary = new int[4][4];
  7. static boolean found = false;
  8.  
  9. public static void main(String[] args) {
  10. Scanner input = new Scanner(System.in);
  11. k = input.nextInt();
  12. for (int i = 1; i <= 16; i++)
  13. used[i] = false;
  14. if (k < 70) {
  15. recursion(0);
  16. }
  17. else {
  18. k -= 69;
  19. ary[0][0] = 1;
  20. ary[0][1] = 7;
  21. used[1] = true;
  22. used[7] = true;
  23. recursion(2);
  24. }
  25. }
  26.  
  27. public static void recursion(int n) {
  28. int x = n / 4, y = n % 4;
  29. if (found) return;
  30. if (n == 16) {
  31. k--;
  32. if (k == 0) {
  33. printMagicSquare();
  34. found = true;
  35. }
  36. return;
  37. }
  38. for (int i = 1; i <= 16; i++) {
  39. if (!used[i]) {
  40. if (x == 3 && (ary[0][y] + ary[1][y] + ary[2][y] + i) != 34)
  41. continue;
  42. if (y == 3 && (ary[x][0] + ary[x][1] + ary[x][2] + i) != 34)
  43. continue;
  44. if (x == 3 && y == 0 && (ary[0][3] + ary[1][2] + ary[2][1] + i) != 34)
  45. continue;
  46. if (x == 3 && y == 3 && (ary[0][0] + ary[1][1] + ary[2][2] + i) != 34)
  47. continue;
  48. used[i] = true;
  49. ary[x][y] = i;
  50. recursion(n + 1);
  51. used[i] = false;
  52. }
  53. }
  54. }
  55.  
  56. public static void printMagicSquare() {
  57. for (int i = 0; i < 4; i++) {
  58. for (int j = 0; j < 3; j++) {
  59. System.out.print(ary[i][j] + " ");
  60. }
  61. System.out.println(ary[i][3]);
  62. }
  63. }
  64. }
  65. Java代码

main中原本是直接调用recursion(0),一运行,尼玛运行超时!评测结果如下:

遂加入了那个if(k<70)的判断语句,把上边两个较大的节点也通过了。

但这很不靠谱,因为这题简单,k限制在100以内。再大一些的话,用条件判断是解决不了问题的(除非有超强毅力写一大堆if,全体遍历一遍自动生成if语句倒是个办法)。

三、C解答

于是我把代码复制到VC中,删掉class,把boolean类型改成int类型,去掉了那个if(k<70)的判断语句,代码如下:

  1.  C代码
  2. #include <stdio.h>
  3. int used[17]; //0-false 1-true
  4. int k;
  5. int ary[4][4];
  6. int found = 0;
  7. void recursion(int n);
  8. void printMagicSquare();
  9. int main() {
  10. int i;
  11. scanf("%d", &k);
  12. for (i = 1; i <= 16; i++)
  13. used[i] = 0;
  14. // if (k < 70) {
  15. recursion(0);
  16. /* }
  17. else {
  18. k -= 69;
  19. ary[0][0] = 1;
  20. ary[0][1] = 7;
  21. used[1] = 1;
  22. used[7] = 1;
  23. recursion(2);
  24. }*/
  25. return 0;
  26. }
  27.  
  28. void recursion(int n) {
  29. int x = n / 4, y = n % 4;
  30. int i;
  31. if (found) return;
  32. if (n == 16) {
  33. k--;
  34. if (k == 0) {
  35. printMagicSquare();
  36. found = 1;
  37. }
  38. return;
  39. }
  40. for (i = 1; i <= 16; i++) {
  41. if (!used[i]) {
  42. if (x == 3 && (ary[0][y] + ary[1][y] + ary[2][y] + i) != 34)
  43. continue;
  44. if (y == 3 && (ary[x][0] + ary[x][1] + ary[x][2] + i) != 34)
  45. continue;
  46. if (x == 3 && y == 0 && (ary[0][3] + ary[1][2] + ary[2][1] + i) != 34)
  47. continue;
  48. if (x == 3 && y == 3 && (ary[0][0] + ary[1][1] + ary[2][2] + i) != 34)
  49. continue;
  50. used[i] = 1;
  51. ary[x][y] = i;
  52. recursion(n + 1);
  53. used[i] = 0;
  54. }
  55. }
  56. }
  57. void printMagicSquare() {
  58. int i, j;
  59. for (i = 0; i < 4; i++) {
  60. for (j = 0; j < 3; j++) {
  61. printf("%d ", ary[i][j]);
  62. }
  63. printf("%d\n", ary[i][3]);
  64. }
  65. }
  66. C代码

这次的评测结果如下:

亮瞎狗眼有木有!!!

之前在看斯坦福《编程方法学》公开课视频时,老师有说,Java的运行效率比普通语言慢3倍左右。从上面的运行时间看的确差不多。但是在同一数量级上的。

但本题中,最深17层的递归,Java用了34MB内存,C语言只用了808KB,差距非常大。

以我目前所学的,有以下猜测:

1、Java运行于Java虚拟机上,装载字节文件等本身需要消耗内存空间。

2、Java中的数组都是类,封装了很多数据域和方法,占用一定内存空间;C中数组就是一段连续的内存空间,相对小巧。

3、Java中的栈中,递归时压栈的信息丰富很多,除了跟C一样的返回地址、参数信息,Java中还会保存异常处理链等地址、参数,所以每次递归会占用不少内存。

也不知上述猜测是否是主要原因,还请Java方面的前辈指教~

---------------------------------------------------这也是切割线--------------------------------------------------

鉴于想知道清橙OJ到底有没有把虚拟机的内存也算进程序运行内存,我去提交了A+B Problem.

清华的清橙网:http://oj.tsinsen.com

北大的POJ:http://poj.org

A+B Problem是绝大多数在线评测网站的第一题,内容为:

问题描述

  输入A,B。
  输出A+B。
输入格式
  输入包含两个整数A,B,用一个空格分隔。
输出格式
  输出一个整数,表示A+B的值。
样例输入
5 8
样例输出
13
数据规模和约定
  -1,000,000,000<=A,B<=1,000,000,000。

我分别写了Java和C的代码,如下:

  1.  C Code
  2. #include <stdio.h>
  3. int main() {
  4. int a, b;
  5. scanf("%d %d", &a, &b);
  6. printf("%d\n", a+b);
  7. return 0;
  8. }
  9. C Code
  1.  Java Code
  2. import java.util.Scanner;
  3. public class Main {
  4. public static void main(String[] args) {
  5. Scanner input = new Scanner(System.in);
  6. int a = input.nextInt(), b = input.nextInt();
  7. System.out.println(a+b);
  8. }
  9. }
  10. Java Code

一、清华-清橙

清橙上JAVA的评测结果为:

评测点编号 评测结果 得分 运行时间 内存使用
1
正确
10.00
109ms
34.21MB
2
正确
10.00
93ms
34.23MB
3
正确
10.00
109ms
34.24MB
4
正确
10.00
125ms
34.20MB
5
正确
10.00
109ms
34.24MB
6
正确
10.00
125ms
34.24MB
7
正确
10.00
93ms
34.24MB
8
正确
10.00
109ms
34.24MB
9
正确
10.00
109ms
34.21MB
10
正确
10.00
93ms
34.21MB

C的评测结果为:

评测点编号 评测结果 得分 运行时间 内存使用
1
正确
10.00
0ms
784.0KB
2
正确
10.00
0ms
784.0KB
3
正确
10.00
0ms
784.0KB
4
正确
10.00
0ms
784.0KB
5
正确
10.00
0ms
784.0KB
6
正确
10.00
0ms
784.0KB
7
正确
10.00
0ms
784.0KB
8
正确
10.00
0ms
784.0KB
9
正确
10.00
0ms
784.0KB
10
正确
10.00
0ms
784.0KB

跟上边的递归题目比较,发现,java的内存占用始终在34MB左右,C的内存占用从808K降低至784K。

结论:清橙不靠谱。。。把java虚拟机也算进去了。。。

以前上程设导论课有些题目规定占用内存不许超过1MB,用java妥妥死翘。。。Otz。。。

二、北大-POJ

既然清华不靠谱,我就打开北大的也试试,程序还是上面两个,结果如下:

Java:  3024K  735MS

C:    164K  16MS

我表示凌乱了。。。不知道这个是怎么计算的。。。

求问怎么自己测试。。。

 
 

OJ题目JAVA与C运行效率对比的更多相关文章

  1. 【Java】深深跪了,OJ题目Java与C运行效率对比(附带清华北大OJ内存计算的对比)

    看了园友的评论之后,我也好奇清橙OJ是怎么计算内存占用的.重新测试的情况附在原文后边. -------------------------------------- 这是切割线 ----------- ...

  2. java OJ题目判断输入结束(与C语言的EOF结束等价)

    /* * java 作Oj题目是会有输入若干数据的情况,不好判断输入结束符, * 类似于C语言中的EOF符号 * 在这里提供了一种方法 * */ import java.util.Iterator; ...

  3. 九度oj 题目1087:约数的个数

    题目链接:http://ac.jobdu.com/problem.php?pid=1087 题目描述: 输入n个整数,依次输出每个数的约数的个数 输入: 输入的第一行为N,即数组的个数(N<=1 ...

  4. hdu 1284 关于钱币兑换的一系列问题 九度oj 题目1408:吃豆机器人

    钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  5. 九度OJ 题目1384:二维数组中的查找

    /********************************* * 日期:2013-10-11 * 作者:SJF0115 * 题号: 九度OJ 题目1384:二维数组中的查找 * 来源:http ...

  6. 在Web开发方面Java跟PHp八大对比

    在Web开发方面Java跟PHp八大对比 <本文摘自百度经验,用来简单对比一下这两种语言> 一. 语言比较 PHP是解释执行的服务器脚本语言,首先php有简单容易上手的特点.语法和c语言比 ...

  7. 十分钟让你明白Objective-C的语法(和Java、C++的对比)

    很多想开发iOS,或者正在开发iOS的程序员以前都做过Java或者C++,当第一次看到Objective-C的代码时都会头 疼,Objective-C的代码在语法上和Java, C++有着很大的区别, ...

  8. Java, C#, Swift语法对比速查表

    原文:Java, C#, Swift语法对比速查表   Java 8 C# 6 Swift 变量 类型 变量名; 类型 变量名; var 变量名 : 类型; 变量(类型推断) N/A var 变量名= ...

  9. 刘汝佳黑书 pku等oj题目

    原文地址:刘汝佳黑书 pku等oj题目[转]作者:小博博Mr 一.动态规划参考资料:刘汝佳<算法艺术与信息学竞赛><算法导论> 推荐题目:http://acm.pku.edu. ...

随机推荐

  1. 【百度地图API】百度API卫星图使用方法和卫星图对比工具

    原文:[百度地图API]百度API卫星图使用方法和卫星图对比工具 百度地图API推出卫星图接口也有一个月啦~ 本文除了介绍如何使用百度地图API来操作卫星图外,还顺带制作了个卫星图对比工具. 一.百度 ...

  2. SharePoint 2013 搜索SharePoint 特定列和特定文档(自己定义搜索)

    SharePoint 2013 搜索SharePoint 特定列和特定文档 1,操作步骤和图例,因语言和版本号的不同 我尽量使用抓图方式. 2.  In Central Administration, ...

  3. easyui datagrid 单元格编辑 自动聚焦 、全选

    $.extend($.fn.datagrid.methods, { editCell: function (jq, param) { return jq.each(function () { var ...

  4. Errors occurred during the build. Errors running builder &#39;JavaScript Validator&#39; on

    eclipse又一次编译时候就会报错Errors occurred during the build. Errors running builder 'JavaScript Validator' on ...

  5. 健身小管家--android app源码

    把做了近一个月的android程序源码放出来,里面包括但不限于如下内容: 1. 简单的android项目结构 2. 通用的adapter,不再为每一个ListView都写一个adapter,只要用此一 ...

  6. 使用flex和bison实现的sql引擎解析

    因为老师要求,近期在做oceanbase存储过程的实现,在oceanbase 0.4曾经是不支持存储过程的.实现的主要步骤主要包含 1.语法解析 2.词法解析 3.详细运行语法树的步骤 如今先来说说语 ...

  7. IOS科研IOS开发笔记学习基础知识

    这篇文章是我的IOS学习笔记,他们是知识的基础,在这里,根据记录的查询后的条款. 1,UIScrollView能完毕滚动的功能. 示比例如以下: UIScrollView *tableScrollVi ...

  8. 最新HTML BroadcastChannel API引荐

    HTML BroadcastChannel API 当前浏览器中只有Firefox38唯一能支持BroadcastChannel API(在编写本文的时间点),而Firefox38官方宣称要到2015 ...

  9. JavaScript超大整数加法

    原文:JavaScript超大整数加法 什么是「超大整数」? JavaScript 采用 IEEE754标准 中的浮点数算法来表示数字 Number. 我也没花时间去详细了解 IEEE754标准 ,但 ...

  10. python向mysql中存储JSON及Nodejs取出

    虽然把JSON数据存入mysql也是比较蛋疼,但是相比使用Nodejs嵌套处理多个mysql查询并拼接返回数据也算是没mongo时的一个折中方案了. 我使用python拼接了一个json格式的字符串, ...