【发布时间】:2015-06-10 08:57:33
【问题描述】:
如果我有 N x N 二维数组并且名称是 a.
int a[N][N];
当我在任意数组中插入任意值,例如a[N-1][N-1]=1,需要多少时间?
O(N^2) 或 O(1)?
【问题讨论】:
-
如果您必须遍历整个数组及其本身就是数组的元素,那就是
O(n^2)。像这样的简单赋值通常是一条 CPU 指令,所以它是O(1)。
如果我有 N x N 二维数组并且名称是 a.
int a[N][N];
当我在任意数组中插入任意值,例如a[N-1][N-1]=1,需要多少时间?
O(N^2) 或 O(1)?
【问题讨论】:
O(n^2)。像这样的简单赋值通常是一条 CPU 指令,所以它是 O(1)。
你没有插入,对吧?您正在分配,直接到特定地址,您无需事先确定正确的位置。
也就是说你不需要做任何循环,不需要经过任何计算,找到位置和分配,内存已经分配好了。
所以它是 O(1),常量与输入无关。
【讨论】:
由于您将值直接分配给数组中的特定位置,因此 ORDER 将为 O(1)
如果您通过 2 个循环对其进行迭代,那么它将是 O(n^2),因为对于每个 i 都会有一个完整的 j 迭代。例如:
for(int i=0; i<n;i++){
for(int j=0; j<n;j++){
}
}
【讨论】:
【讨论】:
c 中的赋值操作可能会被威胁为原语的 O(1)
但是:如果你要为随机位置做很多任务,其他玩家会出现在场上......
考虑以下 2 个示例:
ex1.c:
#define W 1<<12
#define H W
int a[H][W];
int main(){
for(int j=0;j< W ;j++){
for(int i=0;i< H ;i++){
a[i][j]=1;
}
}
return 0;
}
ex2.cpp:
#define W 1<<12
#define H W
int a[H][W];
int main(){
for(int j=0;j< H ;j++){
for(int i=0;i< W ;i++){
a[i][j]=1;
}
}
return 0;
}
CFLAGS=-O3 g++ ex1.c -o e1 && g++ ex2.c -o e2 && time ./e1 && time ./e2 && time ./e1
user 0m0.332s
user 0m0.048s
user 0m0.320s
如您所见,ex1 速度较慢!
取决于所使用的编译器优化级别及其能力,这两者的行为可能会非常不同,即使它们的行为相同
如果你正在做一些随机访问,cpu L1 缓存将开始丢失页面,这将导致一些浪费的周期来拉/放页面。 如果 L2 能够为 L1 的失误提供服务,那没关系 - 如果 L2 有失误,L2 级别也会发生同样的情况……我想你明白了;)
更多: http://en.wikipedia.org/wiki/CPU_cache
您甚至可能会造成数据危害,它的影响要小得多 - 但非常有趣 http://en.wikipedia.org/wiki/Hazard_%28computer_architecture%29#Data_hazards
【讨论】: