• [Python] 二维数组初始化实践


    背景

    参考博客Python二维数组初始化问题_NobiShinnosuke的博客-CSDN博客_python 二维数组初始化,文中提到正确的初始化方式是a = [[0 for j in range(n)] for i in range(n)],错误的初始化方式a = [0 * n] * n。

    第一种正确初始化方式:n * n个元素直接从第一个元素生成而来,一开始的时候大伙都是第一个元素的快捷方式,找任意行任意列的元素都会找到第一个元素。当其他元素有了自己的值以后,就变成独立的元素啦。
    第二种初始化方式:先由一个元素生成一行,再以这一行生成其他行。所以,即使其他行的某个元素改变了,其实也只是在改变第一行的元素。

    本质上,两种初始化方式,是深拷贝与浅拷贝的区别(python中的深拷贝和浅拷贝 - 丫丫tester - 博客园

    最直观的理解就是:
    1.深拷贝,拷贝的程度深,自己新开辟了一块内存,将被拷贝内容全部拷贝过来了;
    2.浅拷贝,拷贝的程度浅,只拷贝原数据的首地址,然后通过原数据的首地址,去获取内容。
    两者的优缺点对比:
    (1)深拷贝拷贝程度高,将原数据复制到新的内存空间中。改变拷贝后的内容不影响原数据内容。但是深拷贝耗时长,且占用内存空间。
    (2)浅拷贝拷贝程度低,只复制原数据的地址。其实是将副本的地址指向原数据地址。修改副本内容,是通过当前地址指向原数据地址,去修改。所以修改副本内容会影响到原数据内容。但是浅拷贝耗时短,占用内存空间少。

    实践

    实践四种方式:

    方式一:

    1. dp_ = [0] * (l2 + 1)
    2. dp = [dp_ for i in range(l1 + 1)]

    方式二:

    1. dp_ = [0 for j in range(l2 + 1)]
    2. dp = [dp_ for i in range(l1 + 1)]

    方式三:

    dp = [[0] * (l2 + 1)]*(l1 + 1)

    方式四:

    dp = [[0] * (l2 + 1) for i in range(l1 + 1)]

    方式五:

    dp = [[0 for j in range(l2 + 1)] for i in range(l1 + 1)]

    其中,只有方式四、方式五是work的。

    方式一、二、三本质上都是先由一个元素生成一行,再以这一行生成其他行。

    方式三比较明显,需要注意下方式一、方式二,错误比较隐晦。

    验证

    最长公共子串这道题可以使用动态规划来做,用上面五种初始化二维数组的方式验证下。

    描述

    给定两个字符串str1和str2,输出两个字符串的最长公共子串

    题目保证str1和str2的最长公共子串存在且唯一。 

    数据范围: 1 \le |str1|,|str2| \le 50001≤∣str1∣,∣str2∣≤5000
    要求: 空间复杂度 O(n^2)O(n2),时间复杂度 O(n^2)O(n2)

    示例1

    输入:

    "1AB2345CD","12345EF"

    返回值:

    "2345"
    


    代码

    1. #!/usr/bin/env python
    2. # coding=utf-8
    3. # Python version is 2.7,
    4. def findCommonStr(str1, str2, init_type=1):
    5. l1 = len(str1)
    6. l2 = len(str2)
    7. if init_type==1:
    8. dp_ = [0] * (l2 + 1)
    9. dp = [dp_ for i in range(l1 + 1)]
    10. elif init_type==2:
    11. dp_ = [0 for j in range(l2 + 1)]
    12. dp = [dp_ for i in range(l1 + 1)]
    13. elif init_type==3:
    14. dp = [[0] * (l2 + 1)] * (l1 + 1)
    15. elif init_type==4:
    16. dp = [[0] * (l2 + 1) for i in range(l1 + 1)]
    17. else:
    18. dp = [[0 for j in range(l2 + 1)] for i in range(l1 + 1)]
    19. max_length = 0
    20. max_last_index = 0
    21. for i in range(1, l1 + 1):
    22. for j in range(1, l2 + 1):
    23. if str1[i - 1] == str2[j - 1]:
    24. dp[i][j] = dp[i - 1][j - 1] + 1
    25. print(i, j, dp[i - 1][j - 1], dp[i][j])
    26. if dp[i][j] > max_length:
    27. max_length = dp[i][j]
    28. max_last_index = i - 1
    29. else:
    30. dp[i][j] = 0
    31. return str1[max_last_index - max_length + 1:max_last_index + 1]
    32. if __name__ == '__main__':
    33. print('1')
    34. res = findCommonStr('abcdefg', 'eebcdwwf', 1)
    35. print('result:',res)
    36. print('2')
    37. res = findCommonStr('abcdefg', 'eebcdwwf', 2)
    38. print('result:', res)
    39. print('3')
    40. res = findCommonStr('abcdefg', 'eebcdwwf', 3)
    41. print('result:', res)
    42. print('4')
    43. res = findCommonStr('abcdefg', 'eebcdwwf', 4)
    44. print('result:', res)
    45. print('5')
    46. res = findCommonStr('abcdefg', 'eebcdwwf', 5)
    47. print('result:', res)

    打印结果:

    1. 1
    2. 2 3 0 1
    3. 3 4 0 1
    4. 4 5 0 1
    5. 5 1 0 1
    6. 5 2 1 2
    7. 6 8 0 1
    8. result: de
    9. 2
    10. 2 3 0 1
    11. 3 4 0 1
    12. 4 5 0 1
    13. 5 1 0 1
    14. 5 2 1 2
    15. 6 8 0 1
    16. result: de
    17. 3
    18. 2 3 0 1
    19. 3 4 0 1
    20. 4 5 0 1
    21. 5 1 0 1
    22. 5 2 1 2
    23. 6 8 0 1
    24. result: de
    25. 4
    26. 2 3 0 1
    27. 3 4 1 2
    28. 4 5 2 3
    29. 5 1 0 1
    30. 5 2 0 1
    31. 6 8 0 1
    32. result: bcd
    33. 5
    34. 2 3 0 1
    35. 3 4 1 2
    36. 4 5 2 3
    37. 5 1 0 1
    38. 5 2 0 1
    39. 6 8 0 1
    40. result: bcd
    41. Process finished with exit code 0

    内存地址

    id() 函数返回对象的唯一标识符,标识符是一个整数。

    CPython 中 id() 函数用于获取对象的内存地址。

    1. if __name__ == '__main__':
    2. l1 = 1
    3. l2 = 1
    4. dp_ = [0] * (l2 + 1)
    5. dp = [dp_ for i in range(l1 + 1)]
    6. print('dp_ = [0] * (l2 + 1)')
    7. print('dp = [dp_ for i in range(l1 + 1)]')
    8. print(id(dp[0]))
    9. print(id(dp[1]))
    10. print(id(dp[0][0]))
    11. print(id(dp[0][1]))
    12. print(id(dp[1][0]))
    13. print(id(dp[1][1]))
    14. dp[0][0] = 1
    15. print('dp[0][0] = 1')
    16. print(id(dp[0][0]))
    17. print(id(dp[0][1]))
    18. print(id(dp[1][0]))
    19. print(id(dp[1][1]))
    20. n = 2
    21. dp_ = [0 for j in range(l2 + 1)]
    22. dp = [dp_ for i in range(l1 + 1)]
    23. print('dp_ = [0 for j in range(l2 + 1)]')
    24. print('dp = [dp_ for i in range(l1 + 1)]')
    25. print(id(dp[0]))
    26. print(id(dp[1]))
    27. print(id(dp[0][0]))
    28. print(id(dp[0][1]))
    29. print(id(dp[1][0]))
    30. print(id(dp[1][1]))
    31. dp[0][0] = 1
    32. print('dp[0][0] = 1')
    33. print(id(dp[0][0]))
    34. print(id(dp[0][1]))
    35. print(id(dp[1][0]))
    36. print(id(dp[1][1]))
    37. dp = [[0] * (l2 + 1)] * (l1 + 1)
    38. print('[[0] * (l2 + 1)] * (l1 + 1)')
    39. print(id(dp[0]))
    40. print(id(dp[1]))
    41. print(id(dp[0][0]))
    42. print(id(dp[0][1]))
    43. print(id(dp[1][0]))
    44. print(id(dp[1][1]))
    45. dp[0][0] = 1
    46. print('dp[0][0] = 1')
    47. print(id(dp[0][0]))
    48. print(id(dp[0][1]))
    49. print(id(dp[1][0]))
    50. print(id(dp[1][1]))
    51. dp = [[0] * (l2 + 1) for i in range(l1 + 1)]
    52. print('dp = [[0] * (l2 + 1) for i in range(l1 + 1)]')
    53. print(id(dp[0]))
    54. print(id(dp[1]))
    55. print(id(dp[0][0]))
    56. print(id(dp[0][1]))
    57. print(id(dp[1][0]))
    58. print(id(dp[1][1]))
    59. dp[0][0] = 1
    60. print('dp[0][0] = 1')
    61. print(id(dp[0][0]))
    62. print(id(dp[0][1]))
    63. print(id(dp[1][0]))
    64. print(id(dp[1][1]))
    65. dp = [[0 for j in range(l2 + 1)] for i in range(l1 + 1)]
    66. print('dp = [[0 for j in range(l2 + 1)] for i in range(l1 + 1)]')
    67. print(id(dp[0]))
    68. print(id(dp[1]))
    69. print(id(dp[0][0]))
    70. print(id(dp[0][1]))
    71. print(id(dp[1][0]))
    72. print(id(dp[1][1]))
    73. dp[0][0] = 1
    74. print('dp[0][0] = 1')
    75. print(id(dp[0][0]))
    76. print(id(dp[0][1]))
    77. print(id(dp[1][0]))
    78. print(id(dp[1][1]))

    打印结果:

    1. dp_ = [0] * (l2 + 1)
    2. dp = [dp_ for i in range(l1 + 1)]
    3. 4349485256
    4. 4349485256
    5. 4304854112
    6. 4304854112
    7. 4304854112
    8. 4304854112
    9. dp[0][0] = 1
    10. 4304854144
    11. 4304854112
    12. 4304854144
    13. 4304854112
    14. dp_ = [0 for j in range(l2 + 1)]
    15. dp = [dp_ for i in range(l1 + 1)]
    16. 4349487048
    17. 4349487048
    18. 4304854112
    19. 4304854112
    20. 4304854112
    21. 4304854112
    22. dp[0][0] = 1
    23. 4304854144
    24. 4304854112
    25. 4304854144
    26. 4304854112
    27. dp = [[0] * (l2 + 1)] * (l1 + 1)
    28. 4349485256
    29. 4349485256
    30. 4304854112
    31. 4304854112
    32. 4304854112
    33. 4304854112
    34. dp[0][0] = 1
    35. 4304854144
    36. 4304854112
    37. 4304854144
    38. 4304854112
    39. dp = [[0] * (l2 + 1) for i in range(l1 + 1)]
    40. 4349486792
    41. 4349486728
    42. 4304854112
    43. 4304854112
    44. 4304854112
    45. 4304854112
    46. dp[0][0] = 1
    47. 4304854144
    48. 4304854112
    49. 4304854112
    50. 4304854112
    51. dp = [[0 for j in range(l2 + 1)] for i in range(l1 + 1)]
    52. 4349485256
    53. 4349216072
    54. 4304854112
    55. 4304854112
    56. 4304854112
    57. 4304854112
    58. dp[0][0] = 1
    59. 4304854144
    60. 4304854112
    61. 4304854112
    62. 4304854112
    63. Process finished with exit code 0

    对比上面五种方式,说明:

    在正确的初始化方式中,对于二维数组的每一行,每行的地址都不同。对于单个元素而言,都是直接从第一个元素生成而来,一开始的时候大伙都是第一个元素的快捷方式,找任意行任意列的元素都会找到第一个元素。当其他元素有了自己的值以后,就变成独立的元素,且只会改变自己,不会改变同一列其他行的元素。

    而如果先由一个元素生成一行,再以这一行生成其他行,每行的地址都相同。所以,即使其他行的某个元素改变了,其实也只是在改变第一行的元素。

  • 相关阅读:
    el-select,el-option下拉选择框
    LeetCode讲解篇之77. 组合
    Spring面试题
    【源码课件+教程】Python入门教程_Python400集持续更新
    vivo面试-Java
    Codeforces Round #816 (Div. 2)补题(A-E)
    [Git]Git - GitHub远程仓库操作
    CFCA证书——基于SM2/3算法的安全信任
    给按钮的边框和文字设置不同的背景色
    [acwing周赛复盘] 第 60 场周赛20220716
  • 原文地址:https://blog.csdn.net/u013250416/article/details/127417526