OJ题目JAVA与C运行效率对比
【JAVA】深深跪了,OJ题目JAVA与C运行效率对比(附带清华北大OJ内存计算的对比)
看了园友的评论之后,我也好奇清橙OJ是怎么计算内存占用的。重新测试的情况附在原文后边。
-------------------------------------- 这是切割线 --------------------------------------------
最近自学Java,试着用Java刷几道OJ的题来熟悉基本语法。
起初几道简单题,没太留意程序的执行效率。今天做了一道简单的递归题,竟然运行超时了!由于本人算法方面功底太差,不懂的如何优化,想了个投机的办法应付了过去。但又觉得不可思议,照以前用C语言刷OJ的经验,不可能这种规模的数据就运行超时。于是我将代码从eclipse复制黏贴到VC中,改成C程序,重新测试,结果惊人。
以下是详细情况:
一、题目
题目位于:http://oj.tsinsen.com/ViewGProblem.page?gpid=A1069
问题描述
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之前
12 14 3 5
13 7 10 4
8 11 6 9
Java代码
import java.util.Scanner;
public class Main {
static boolean[] used = new boolean[17];
static int k;
static int[][] ary = new int[4][4];
static boolean found = false; public static void main(String[] args) {
Scanner input = new Scanner(System.in);
k = input.nextInt();
for (int i = 1; i <= 16; i++)
used[i] = false;
if (k < 70) {
recursion(0);
}
else {
k -= 69;
ary[0][0] = 1;
ary[0][1] = 7;
used[1] = true;
used[7] = true;
recursion(2);
}
} public static void recursion(int n) {
int x = n / 4, y = n % 4;
if (found) return;
if (n == 16) {
k--;
if (k == 0) {
printMagicSquare();
found = true;
}
return;
}
for (int i = 1; i <= 16; i++) {
if (!used[i]) {
if (x == 3 && (ary[0][y] + ary[1][y] + ary[2][y] + i) != 34)
continue;
if (y == 3 && (ary[x][0] + ary[x][1] + ary[x][2] + i) != 34)
continue;
if (x == 3 && y == 0 && (ary[0][3] + ary[1][2] + ary[2][1] + i) != 34)
continue;
if (x == 3 && y == 3 && (ary[0][0] + ary[1][1] + ary[2][2] + i) != 34)
continue;
used[i] = true;
ary[x][y] = i;
recursion(n + 1);
used[i] = false;
}
}
} public static void printMagicSquare() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(ary[i][j] + " ");
}
System.out.println(ary[i][3]);
}
}
}
Java代码
main中原本是直接调用recursion(0),一运行,尼玛运行超时!评测结果如下:

遂加入了那个if(k<70)的判断语句,把上边两个较大的节点也通过了。
但这很不靠谱,因为这题简单,k限制在100以内。再大一些的话,用条件判断是解决不了问题的(除非有超强毅力写一大堆if,全体遍历一遍自动生成if语句倒是个办法)。
三、C解答
于是我把代码复制到VC中,删掉class,把boolean类型改成int类型,去掉了那个if(k<70)的判断语句,代码如下:
C代码
#include <stdio.h>
int used[17]; //0-false 1-true
int k;
int ary[4][4];
int found = 0;
void recursion(int n);
void printMagicSquare();
int main() {
int i;
scanf("%d", &k);
for (i = 1; i <= 16; i++)
used[i] = 0;
// if (k < 70) {
recursion(0);
/* }
else {
k -= 69;
ary[0][0] = 1;
ary[0][1] = 7;
used[1] = 1;
used[7] = 1;
recursion(2);
}*/
return 0;
} void recursion(int n) {
int x = n / 4, y = n % 4;
int i;
if (found) return;
if (n == 16) {
k--;
if (k == 0) {
printMagicSquare();
found = 1;
}
return;
}
for (i = 1; i <= 16; i++) {
if (!used[i]) {
if (x == 3 && (ary[0][y] + ary[1][y] + ary[2][y] + i) != 34)
continue;
if (y == 3 && (ary[x][0] + ary[x][1] + ary[x][2] + i) != 34)
continue;
if (x == 3 && y == 0 && (ary[0][3] + ary[1][2] + ary[2][1] + i) != 34)
continue;
if (x == 3 && y == 3 && (ary[0][0] + ary[1][1] + ary[2][2] + i) != 34)
continue;
used[i] = 1;
ary[x][y] = i;
recursion(n + 1);
used[i] = 0;
}
}
}
void printMagicSquare() {
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 3; j++) {
printf("%d ", ary[i][j]);
}
printf("%d\n", ary[i][3]);
}
}
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。
我分别写了Java和C的代码,如下:
C Code
#include <stdio.h>
int main() {
int a, b;
scanf("%d %d", &a, &b);
printf("%d\n", a+b);
return 0;
}
C Code
Java Code
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int a = input.nextInt(), b = input.nextInt();
System.out.println(a+b);
}
}
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运行效率对比的更多相关文章
- 【Java】深深跪了,OJ题目Java与C运行效率对比(附带清华北大OJ内存计算的对比)
看了园友的评论之后,我也好奇清橙OJ是怎么计算内存占用的.重新测试的情况附在原文后边. -------------------------------------- 这是切割线 ----------- ...
- java OJ题目判断输入结束(与C语言的EOF结束等价)
/* * java 作Oj题目是会有输入若干数据的情况,不好判断输入结束符, * 类似于C语言中的EOF符号 * 在这里提供了一种方法 * */ import java.util.Iterator; ...
- 九度oj 题目1087:约数的个数
题目链接:http://ac.jobdu.com/problem.php?pid=1087 题目描述: 输入n个整数,依次输出每个数的约数的个数 输入: 输入的第一行为N,即数组的个数(N<=1 ...
- hdu 1284 关于钱币兑换的一系列问题 九度oj 题目1408:吃豆机器人
钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- 九度OJ 题目1384:二维数组中的查找
/********************************* * 日期:2013-10-11 * 作者:SJF0115 * 题号: 九度OJ 题目1384:二维数组中的查找 * 来源:http ...
- 在Web开发方面Java跟PHp八大对比
在Web开发方面Java跟PHp八大对比 <本文摘自百度经验,用来简单对比一下这两种语言> 一. 语言比较 PHP是解释执行的服务器脚本语言,首先php有简单容易上手的特点.语法和c语言比 ...
- 十分钟让你明白Objective-C的语法(和Java、C++的对比)
很多想开发iOS,或者正在开发iOS的程序员以前都做过Java或者C++,当第一次看到Objective-C的代码时都会头 疼,Objective-C的代码在语法上和Java, C++有着很大的区别, ...
- Java, C#, Swift语法对比速查表
原文:Java, C#, Swift语法对比速查表 Java 8 C# 6 Swift 变量 类型 变量名; 类型 变量名; var 变量名 : 类型; 变量(类型推断) N/A var 变量名= ...
- 刘汝佳黑书 pku等oj题目
原文地址:刘汝佳黑书 pku等oj题目[转]作者:小博博Mr 一.动态规划参考资料:刘汝佳<算法艺术与信息学竞赛><算法导论> 推荐题目:http://acm.pku.edu. ...
随机推荐
- uva 12003 Array Transformer (大规模阵列)
白皮书393页面. 乱搞了原始数组中.其实用另一种阵列块记录. 你不能改变原始数组. 请注意,与原来的阵列和阵列块的良好关系,稍微细心处理边境.这是不难. #include <cstdio> ...
- linux_设置开机自启动程序脚本
设置开机自启动
- 去除win7 64位系统桌面图标小箭头
http://blog.csdn.net/pipisorry/article/details/24865195 在桌面新建一个文本文档 去除箭头.txt,把例如以下代码粘贴到文档中reg add &q ...
- Java中关于继承、类、多态、接口的知识点
继承 含义:在面向对象编程中,可以通过扩展一个已有的类,并继承该类的属性和行为,来创建一个新的类 优点:1)代码的重用性:2)子类扩展父类的属性和方法:3)父类的属性和方法可用于子类:4)设计应用程序 ...
- ApacheBench(ab)使用简介
网站性能压力测试是服务器网站性能调优过程中必不可缺少的一环.只有让服务器处在高压情况下,才能真正体现出软件.硬件等各种设置不当所暴露出的问题. 性能测试工具目前最常见的有以下几种:ab.http_lo ...
- svg的自述
svg可缩放矢量图形(Scalable Vector Graphics). SVG 使用 XML 格式定义图像. SVG 是使用 XML 来描述二维图形和绘图程序的语言. 什么是SVG? SVG 指可 ...
- WEB浏览器与服务器通讯过程
以访问网页www.baidu.com为例,下面是使用Wireshark捕捉到的数据: 浏览器先发起一个TCP连接,然后发送GET报文给服务器,服务器之后返回一个Response报文. 从服务器端返回时 ...
- asterisk实时添加sip号码--sqlite篇
原文:asterisk实时添加sip号码--sqlite篇 asterisk实时添加sip号码--sqlite篇 今天尝试用了asterisk的实时模式,往sqlite里面添加一个sip帐号,无需重启 ...
- Spring之IOC容器加载初始化的方式
引言 我们知道IOC容器时Spring的核心,可是如果我们要依赖IOC容器对我们的Bean进行管理,那么我们就需要告诉IOC容易他需要管理哪些Bean而且这些Bean有什么要求,这些工作就是通过通过配 ...
- 安装WindowsXP操作系统(Ghost版) - 初学者系列 - 学习者系列文章
Windows XP的Ghost版是经典的版本.因为XP相对较小些,所以用Ghost起来速度比较快.如果Ghost那个Windows 7之类的,速度就慢了.Windows 7建议还是安装比较快.下面简 ...