2017-02-14 1 views
0

LeetCode 문제 (링크 - click here)를 해결하고있었습니다. 근본적으로 문제는 주어진 이진 트리의 모든 경로를 찾는 것입니다.목록 추가 및 목록 추가와 파이썬에서 변수 목록 범위 차이점

다음과 같은 이진 트리를 고려하십시오.

# Definition for a binary tree node. 
# class TreeNode(object): 
#  def __init__(self, x): 
#   self.val = x 
#   self.left = None 
#   self.right = None 

class Solution(object): 
    def binaryTreePaths(self, root): 
     """ 
     :type root: TreeNode 
     :rtype: List[str] 
     """ 
     res = [] 
     self.dfs(root, [], res) 
     a = [] 
     for path in res: 
      a.append('->'.join([str(i) for i in path])) 
     return a 

    def dfs(self, root, ls, res): 
     if root == None: 
      return 

     ls = ls + [root.val] 
     if not root.left and not root.right: # if it is a leaf 
      res.append(ls) 
     if root.left: 
      self.dfs(root.left, ls, res) 
     if root.right: 
      self.dfs(root.right, ls, res) 

위에서 언급 한 코드가 잘 작동 - 다음과 같이

 
    1 
/ \ 
2  3 
\ 
    5 

내 작업 솔루션입니다. 대신 [[1,2,5],[1,3]] 점점 내가 dfs 호출 후 함수 binaryTreePathsresls.append(root.val)하는 ls = ls + [root.val] 변경하면

  • 다음 함수 dfs에서, 전술 한 같은 경우 [[],[]]
  • 을대로이지만 미묘한 점 I이있다 [[1,3],[1,3]]이 최종 값이 res이됩니다.

정확히 여기 무슨 일이 일어나고 있습니까?

답변

0

코드에 따르면 ls은 유형이 없으며 그 시점에서 초기화하므로 실제로 존재하지 않으므로 .append이라는 오류가 발생합니다. ls = ls + [root.val]ls = [root.val]과 같습니다. 그러므로 그것은 효과적이다.

희망이 도움이됩니다. :)

다음
1

구현이 - 불필요한 클래스없이 - :

def dfs(root, ls, res): 
    if root == None: 
     return 
    ls = ls + [root.val] 
    if not root.left and not root.right: 
     res.append(ls) 
    if root.left: 
     dfs(root.left, ls, res) 
    if root.right: 
     dfs(root.right, ls, res) 

다음은 출력

In [1]: tree = Node(1, Node(2, None, Node(5)), Node(3)) 

In [2]: res = [] 

In [3]: dfs(tree, [], res) 

In [4]: res 
Out[4]: [[1, 2, 5], [1, 3]] 

대에게이야! 그것은 작동합니다. 여기가 .append 함께 : 이제

def dfs(root, ls, res): 
    if root == None: 
     return 
    ls.append(root.val) 
    if not root.left and not root.right: 
     res.append(ls) 
    if root.left: 
     dfs(root.left, ls, res) 
    if root.right: 
     dfs(root.right, ls, res) 

그러나이 시간 ...

In [7]: res = [] 

In [8]: dfs(tree, [], res) 

In [9]: res 
Out[9]: [[1, 2, 5, 3], [1, 2, 5, 3]] 

정말 대단하지. 공지 사항, 두 목록 모든 ... 그들이 이 동일한 목록만큼이나입니다 :

In [10]: [hex(id(r)) for r in res] 
Out[10]: ['0x104285e88', '0x104285e88'] 

아하! 그들은 같은 목록입니다!

최초의 구현이 작동하는 이유는 다음 줄 이유는

ls + [root.val] 

가 만듭니다 (당신이 ls에 재 할당해야하는 이유입니다) 새 목록, 반면 :

ls.append(root.val) 

은 그 자리에서 목록을 변경합니다.

In [20]: print(hex(id(x))) 
0x104216288 

In [21]: x.append(4) 

In [22]: x 
Out[22]: [1, 2, 3, 4] 

In [23]: print(hex(id(x))) 
0x104216288 

그러나 우리가 + 연산자를 사용할 때 발생하는 찾습니다

In [24]: x = [1, 2, 3] 

In [25]: print(hex(id(x))) 
0x1042c8308 

In [26]: x = x + [4] 

In [27]: print(hex(id(x))) 
0x104222588 
우리가 처음 목록을 복사 할 경우 우리는 append을 사용할 수 있습니다

...

In [29]: def dfs(root, ls, res): 
    ...:  if root == None: 
    ...:   return 
    ...:  copy = ls[:] 
    ...:  copy.append(root.val) 
    ...:  if not root.left and not root.right: 
    ...:   res.append(copy) 
    ...:  if root.left: 
    ...:   dfs(root.left, copy, res) 
    ...:  if root.right: 
    ...:   dfs(root.right, copy, res) 
    ...: 

In [30]: 

In [30]: res = [] 

In [31]: dfs(tree, [], res) 

In [32]: res 
Out[32]: [[1, 2, 5], [1, 3]] 

그냥 완성도를 위해서 사용을 증대 된 대입 연산자, 예. some_list += another_list은 목록을 현재 위치에서 수정하며, 본질적으로 some_list.extend(another_list)과 같습니다.

In [38]: x = [1, 2, 3, 4] 

In [39]: print(hex(id(x))) 
0x1045e5d08 

In [40]: x += [5] 

In [41]: x 
Out[41]: [1, 2, 3, 4, 5] 

In [42]: print(hex(id(x))) 
0x1045e5d08