python3(二)刷题遇到的知识点

1.定义数组,初始化数组

我习惯性写成了这样:错误

count = int[60]

正确定义:

count = [0]*60

当然,还可以借用numpy库生成数组,可以得到多维数组:

        print(np.zeros(3))
        print(np.zeros((3,3)))
        print(np.zeros((4,3,2)))

结果:

[0. 0. 0.]

[[0. 0. 0.] [0. 0. 0.] [0. 0. 0.]]

[[[0. 0.] [0. 0.] [0. 0.]] [[0. 0.] [0. 0.] [0. 0.]] [[0. 0.] [0. 0.] [0. 0.]] [[0. 0.] [0. 0.] [0. 0.]]]

 2.定义列表

list = []

 3.python作用域的知识盲点

我太小看了python这门语言,直达我遇到783. 二叉搜索树节点最小距离

首先,一个在编程语言中的基本知识:局部变量将在它的作用域内覆盖同名全局变量,此时对局部变量的更改不会保存到全局变量中,所以我们也不常编写同名变量。

也因为这个常识,其实我很少在java中出现变量作用域的问题,java作用域明确,需要全局变量时可用成员变量。

但在python中我遇到了这样一个问题:

由于inOrder是递归函数,prev和res毫无疑问必须是全局变量,所以下面这段代码是错误

class Solution:
    prev = None
    res = sys.maxsize
    def minDiffInBST(self, root: TreeNode) -> int:
        #定义全局变量
        #None表示空对象,null是空字符‘’
        def inOrder(root):
                if root:
                    inOrder(root.left)
                    if prev is not None:
                        res = min(root.val - prev,res)
                    prev = root.val
                    inOrder(root.right)
        inOrder(root)
        return res

 

其实在java版代码就是上面提到的那个思路,类的成员变量是全局的:

class Solution {
    int ans = Integer.MAX_VALUE;
    TreeNode prev = null;
    public int minDiffInBST(TreeNode root) {
        //二叉树的大小范围在2到100
        inOrder(root);
        return ans;
    }
    //中序遍历
    public void inOrder(TreeNode root){
        if(root == null) return;
        inOrder(root.left);
        if(prev != null) ans = Math.min(ans,root.val-prev.val);
        prev = root;
        inOrder(root.right);
    }
}

那么我想python也可以模仿java这个思路,必然是没错的

class Solution:
    def __init__(self):
        self.prev = None
        self.res = sys.maxsize
    def minDiffInBST(self, root: TreeNode) -> int:
        #定义全局变量
        #None表示空对象,null是空字符‘’
        def inOrder(root):
            if root:
                inOrder(root.left)
                if self.prev is not None:
                    self.res = min(root.val - self.prev,self.res)
                self.prev = root.val
                inOrder(root.right)
        inOrder(root)
        return self.res

 但是这样多没有意思,太小题大做了,完全没有用到python的作用域信息,我觉得这就不算领略到python的精髓。

第一步,我们可以定义全局变量。然后,出来了无数问题:第一个问题,为什么需要显示的用global?同时思考为啥第5行和第8行都需要声明global?

 1 class Solution:
 2     def minDiffInBST(self, root: TreeNode) -> int:
 3         #定义全局变量
 4         #None表示空对象,null是空字符‘’
 5        # global prev,res
 6         prev,res = None,float("inf")
 7         def inOrder(root):
 8             global prev,res
 9             if root:
10                 inOrder(root.left)
11                 if prev is not None:
12                     res = min(root.val - prev,res)
13                 prev = root.val
14                 inOrder(root.right)
15         inOrder(root)
16         return res

 

我刚开始以为第6行定义的变量就是全局变量。这是由于我平时写python代码很多时候没有在类中写,那时候不显示的定义global也具有全局变量的效果。但是在这里prev和res都在函数minDiffInBST()中,如果不显示定义那么就是局部变量。所以正确写法应该将第5行取消注释,定义prev,res是全局变量(有些情况变量已经具有全局变量的意义了,则可省略这一步)

注意第8行,这里再次对变量声明它是全局变量(在函数内部对全局变量进行操作,必须有这一步,如果不修改只是调用则不需要)这是因为如果不声明global,在第14行定义了局部变量,但在第11行已经用到了该局部变量,将报错。

还有一种隐藏写法:nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。

 1 class Solution:
 2     def minDiffInBST(self, root: TreeNode) -> int:
 3         #定义全局变量
 4         #None表示空对象,null是空字符‘’    
 5         prev,res = None,float("inf")
 6         def inOrder(root):
 7             nonlocal prev,res
 8             if root:
 9                 inOrder(root.left)
10                 if prev is not None:
11                     res = min(root.val - prev,res)
12                 prev = root.val
13                 inOrder(root.right)
14         inOrder(root)
15         return res

 

 

 

posted @ 2020-11-09 17:38  随温  阅读(99)  评论(0)    收藏  举报