一道看起来简单的面试题,请大家探讨一下

题目如下:

下面的代码有什么问题?
data = [[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]]
for i in range(3):
    for j in range(3):
        data[j][i] = data[j][i] * 2

坦白地说,我没看出有什么问题,代码意图无非是按列优先的顺序,把二维数据的每个元素放大2倍,有什么要注意的隐患吗?

阅读 2.6k
5 个回答

@Lo_yao_gwet 所讲,按行(data[i][j])和按列(data[j][i])迭代二维数组效率有差别,这个有道理,但原因我不敢苟同。我觉得寻址操作的次数是一样的,python不会缓存data[i]的值使得下次使用data[i]就少了一次寻址操作,并且寻址操作的耗时可以忽略不记。

找到一篇将C二维数组的解释,觉得靠谱:二维数组按行和按列遍历效率
和CPU高速缓存、内存分页调度机制有关。当二维数组大到跨内存页时,效率差别就比较显著了。建议大家看看文章。

data[ji ]= data[j][i]* 2

改成 data[i][j] = data[i][j]* 2
那么下面那行会更省时间。

pythonlist 里面位置只是存放了指针以指向实际的数据,或者子 list

以下是伪代码, 假设没有其他操作

A=a1, a2, a3
B=b1, b2, b3
C=c1, c2, c3
List=A, B, C

以你提供的代码为例,需要如此操作

A, a1, B, b1, C, c1, 
A, a2, B, b2, C, c2, 
A, a3, B, be, C, c3

一共18次访问。

如果以改善版本为例

A,a1, a2, a3, 
B, b1, b2, b3,
C, c1, c2, c3

一共12次访问。

下面是我的测试代码

import time

a=list(range(10000))
b=list(range(10000))
c=list(range(10000))

data = [a,b,c]

#better performance                
start=time.time()        
for i in range(3):
    for j in range(10000):
        data[i][j] = data[i][j] * 2
        
end=time.time()

print(end-start)


a=list(range(10000))
b=list(range(10000))
c=list(range(10000))

data = [a,b,c]

#bad performance                
start2=time.time()        
for i in range(10000):
    for j in range(3):
        data[j][i] = data[j][i] * 2
        
end2=time.time()

print(end2-start2)
        
        
0.01891350746154785
0.02604365348815918                                         [Program finished]
`
  

我不是很熟悉 Python,如果单纯说 问题 的话,那么
for 循环的范围不依据参数变化
万一改了 data 的大小,甚至是个不规则的:

data = [
    [1, 2, 3],
    [4],
    [5, 6],
    [7, 8, 9, 10]
]

就 GG 了。

代码没有问题,出题人有问题。没有明确代码问题的界限,给出相对应假设,单凭一段正常的代码无法判断问题所在。

感觉像是楼上说的。写死list的长度不可取,万一数据变了呢,那你遍历代码岂不是要改。。

list(map(lambda x: list(map(lambda y: y * 2, x)), data))
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题