LeetCode 22.括号生成

题目

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 n = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

思路

这道题我用递归来做,直觉上是设置两个flag,分别叫做needright和remainleft,因为括号有左右必须成对的语法,所以needright用来记录已有多少个孤独的左括号没有和右括号成对,即现在需要多少个右括号,remainleft是说目前还有多少个空余的左括号没有还可以用,因为可以(((这样直接叠加而不造成语法错误。对于remainleft=0和needright=0的情况就是下一个必须添加左括号和右括号。其他的情况就是下面两行,只要先加左后加右就行了。

代码

class Solution(object):
    def generateParenthesis(self, n):
        """
        :type n: int
        :rtype: List[str]
        """
        self.result = []
        self.needright = 1
        self.remainleft = n-1
        self.gp(n, self.needright, self.remainleft,'', '(')
        return self.result

    def gp(self, n, needright, remainleft, succeed, parth):
        if len(succeed) == 2 * n:
            self.result.append(succeed)
            #print('reach')
            return
        succeed += parth
        if remainleft == 0:
            self.gp(n, needright-1, remainleft, succeed, ')')
        elif needright == 0:
            self.gp(n, 1, remainleft-1, succeed, '(')
        else:
            self.gp(n, needright+1, remainleft-1, succeed, '(')
            self.gp(n, needright-1, remainleft, succeed,')')

注意

值得一提的是,这道题让我注意到了python的参数传递方式和对象的不同。

赋值

Python中,一切都是对象,赋值也都是引用。如a=123这个简单的赋值,事实上是解释器在内存中创建了一个对象123,然后再创建了一个对象是个变量a,a里面存放的是123在内存里的地址。

a = 123
b = a
a = '321'

这小段代码实际上是让b也指向了内存中的123。

python值传递还是引用传递

上面说了,python中的赋值是都是引用,但问题在于赋值的变量是什么对象,python中的对象分为可变对象(list,dict,set等)和不可变对象(number, string, tuple等)。

  • 可变对象
    可变对象,该对象所指向的内存中的值可以被改变。变量(准确的说是引用)改变后,实际上是其所指的值直接发生改变,并没有发生复制行为,也没有开辟新的出地址,通俗点说就是原地改变。
  • 不可变对象
    不可变对象,该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。

对于我这道题的代码来说比如说递归了三层以后needright = 2 remainleft = 1,然后继续递归完成一个result.append,之后又返回到这一层,由于needreight和remainleft都是number,属于不可变对象,所以返回来之后就还是2,1,但如果有个变量比如succeed现在不是字符串了,把他设置成一个列表,因为列表是可变对象,如果在后面的递归中对列表进行了改变,那么即使返回到这一层,succeed还是会被改变,不再是刚进入这一层时的succeed了。

下面说一下值传递和引用传递,按照C++的概念

  • 值传递
    对于函数输入的参数对象,函数执行中首先生成对象的一个副本,并在执行过程中对副本进行操作。执行结束后对象不发生改变。
  • 引用传递
    对于函数输入的参数对象,函数在执行过程中对对象本身进行操作;在执行结束后参数对象有可能发生改变函数的值

结合起来看,如果对象是可变对象,那么进行引用传递,如果对象是不可变对象,那么就值传递。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值