트 리 데이터 구조 - 파워 브러시 트 리 문제 알 아야 할 것 (Python)

25272 단어
더 많은 하 이 라이트 내용 을 주목 해 주세요.
나 무 는 중요 한 데이터 구조 이 고 이 진 트 리 는 그 중의 중점 과 난점 이다. 이 진 트 리 에 관 한 기초 지식 은 독자 가 걸음 을 옮 겨 더 많은 내용 을 볼 수 있다.여기 서 우 리 는 나무의 기본 구조 가 python 에서 어떻게 구축 되 고 응용 되 는 지 에 중심 을 두 었 다.
1. 이 진 트 리 의 결 점
두 갈래 나무의 결점 에는 세 개의 실례 변수 가 있다.
  • 결점 값 은 임의의 데이터 형식 일 수 있 지만 정수 가 가장 간단 하 다.
  • 왼쪽 아 이 는 이 진 트 리 노드 이 고 없 으 면 None 로 설정 합 니 다.
  • 오른쪽 아 이 는 이 진 트 리 노드 이 고 없 으 면 None 로 설정 합 니 다.

  • 모든 노드 는 예화 할 때 이 노드 의 값 을 설정 해 야 하 며, 이 노드 는 기본적으로 좌우 아이들 이 모두 None 이 므 로 할당 문 구 를 통 해 추가 해 야 합 니 다.
    class TreeNode:
        """
              
        """
        def __init__(self, x):
            self.val = x            #    
            self.left = None        #    
            self.right = None       #    
    

    2. 이 진 트 리 구축
    여기 서 우 리 는 함 수 를 설계 하여 하나의 목록 을 통 해 이 진 트 리 를 구축 하고 입력 한 목록 은 이 진 트 리 의 차원 순서에 따라 각 요 소 를 제시 합 니 다. 우 리 는 이 진 트 리 의 아래 표지 에 따라 결점 간 의 대응 관 계 를 찾 습 니 다. 아래 에 i 로 표 시 된 노드 의 좌우 아이들 이 목록 에서 의 아래 표 시 는 각각 2i + 1 과 2i + 2 입 니 다.
    def create_tree(nodes):
        """
                   
        :param nodes:       
        :return:        
        """
    
        def helper(node, i):                                    #           ,
    
            if i < len(nodes):                                  #           
                if nodes[i] in ['#', None]:                     #         i     
                    return None                                 #   None
                else:
                    node = TreeNode(nodes[i])                   #       
                    node.left = helper(node.left, 2 * i + 1)    #      ,      
                    node.right = helper(node.right, 2 * i + 2)  #      ,      
                    return node                                 #          i      
            return node                                         #      
    
        root = TreeNode(0)                                      #     
        root = helper(root, 0)                                  #    
        return root                                             #        
    

    만약 에 우리 가 이 진 트 리 를 만 들 려 고 한다 면:
        1
       / \ 
      2   3
     / \ / \
    4  5 6  7
    

    우 리 는 이 함수 만 호출 하면 된다.
    root = create_binary_tree([1, 2, 3, 4, 5, 6, 7])
    

    만약 우리 가 일반 이 진 트 리 를 구축 해 야 한다 면, 예 를 들 어:
        1
       / \ 
      2   3
     /   / 
    4    6  
    

    우 리 는 빈 잎 결점 을 None 또는 '\ #' 로 채 울 것 입 니 다. 마지막 층 의 마지막 몇 개의 결점 이 연속 적 인 빈 결점 이 라면 조작 하지 않 아 도 됩 니 다.
    root = create_binary_tree([1, 2, 3, 4, None, 6])
    

    3. 이 진 트 리 옮 겨 다 니 기
    이 진 트 리 에서 흔히 볼 수 있 는 옮 겨 다 니 는 방식 은 네 가지 가 있 는데 앞 순 서 는 옮 겨 다 니 고 중간 순 서 는 옮 겨 다 니 며 뒤 순 서 는 옮 겨 다 니 며 순서 에 관 한 기초 지식 은 [이 진 트 리 의 옮 겨 다 니 기] 를 참고 할 수 있 고 모든 옮 겨 다 니 는 것 은 재 귀 와 교체 두 가지 방식 으로 이 루어 질 수 있다.
    밤 을 들 어 이 진 트 리 한 그루 에 대해 우 리 는 각각 앞 순서, 중간 순서, 뒤 순서 와 층 서 인쇄 방식 을 사용 했다. 결 과 는 다음 과 같다.
        1
       / \ 
      2   3
     / \ / \
    4  5 6  7
    
      :[1, 2, 4, 5, 3, 6, 7]
      :[4, 2, 5, 1, 6, 3, 7]
      :[4, 5, 2, 6, 7, 3, 1]
      :[1, 2, 3, 4, 5, 6, 7]
    

    순환 실현
    옮 겨 다 니 는 재 귀적 실현 은 더욱 간결 하고 이해 하기 쉬 워 야 한다. 스 택, 대기 열 등 추가 데이터 구 조 를 빌 리 지 않 아 도 된다. 앞 순서, 중간 순서 와 뒤 순서 의 옮 겨 다 니 는 순 서 는 매우 유사 한 실현 방식 이 있 고 유일한 차 이 는 뿌리 노드 와 좌우 아이들 간 의 순서 관계 에 있다.
  • 빈 트 리 를 입력 하면 빈 목록 으로 돌아 갑 니 다.
  • 빈 트 리 가 아 닌 것 을 입력 하면 현재 노드 의 값 을 얻 고 목록 에 저장 합 니 다. 이 함 수 를 재 귀적 으로 호출 하여 왼쪽 트 리 와 오른쪽 트 리 의 옮 겨 다 니 는 결 과 를 얻 습 니 다. (1) 앞 순 서 는 뿌리 노드 + 왼쪽 트 리 + 오른쪽 트 리 입 니 다.(2) 중간 순서: 왼쪽 하위 트 리 + 뿌리 노드 + 오른쪽 하위 트 리;(3) 뒤 순서 옮 겨 다 니 기: 왼쪽 나무 + 오른쪽 나무 + 뿌리 노드.

  • 1. 앞 순서 옮 겨 다 니 기
    def pre_order(node):
        """
            
        :param node:        
        :return:       
        """
        if not node:
            return []
        return [node.val] + pre_order(node.left) + pre_order(node.right)
    

    2. 중간 순서 옮 겨 다 니 기
    def in_order(node):
        """
            
        :param node:        
        :return:       
        """
        if not node:
            return []
        return pre_order(node.left) + [node.val] + pre_order(node.right)
    

    3. 후 순 옮 겨 다 니 기
    def post_order(node):
        """
            
        :param node:        
        :return:       
        """
        if not node:
            return []
        return pre_order(node.left) + pre_order(node.right) + [node.val]
    

    우 리 는 상기 세 가지 옮 겨 다 니 는 방식 을 python 의 lambda 표현 식 으로 빠르게 정의 하 는 것 을 고려 할 수 있 습 니 다. 한 마디 로 함수 만 정의 할 수 있 습 니 다.
    #     
    pre_order = lambda node: [node.val] + pre_order(node.left) + pre_order(node.right) if node else []
    
    #     
    in_order = lambda node: in_order(node.left) + [node.val] + in_order(node.right) if node else []
    
    #     
    post_order = lambda node: post_order(node.left) + post_order(node.right) + [node.val] if node else []
    

    4. 층 차 를 옮 겨 다 닌 다
    우 리 는 목록 을 빌려 층 차 를 옮 겨 다 녔 다.우 리 는 층 차 를 옮 겨 다 니 는 결 과 를 목록 에 포 함 된 구조 로 표시 하고 목록 의 모든 요 소 는 각 층 의 옮 겨 다 니 는 결과 이자 목록 형식 입 니 다.재 귀적 호출 시, 우 리 는 조수 함수 (helper) 를 구축 하여, 수의 한 층 의 한 노드 를 지정 한 층 의 결과 목록 에 추가 하 는 데 사용 합 니 다.
    def level_order(root):
        """
            
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        def helper(node, level):
            """
              node                res 
            :param node:    
            :param level:         
            :return:
            """
            if not node:                            #        
                return                              #   
            else:
                res[level-1].append(node.val)       #                   
                if len(res) == level:               #       ,              
                    res.append([])                  #      
                helper(node.left, level+1)          #      
                helper(node.right, level+1)         #      
        res = [[]]                                  #             
        helper(root, 1)                             #
        return res[:-1]                             #             
    

    반복 실현
    교체 실현 은 재 귀 실현 보다 더욱 복잡 하고 교체 법 으로 이 진 트 리 의 역 사 를 실현 하려 면 대기 열 이나 스 택 등 데이터 구 조 를 빌려 야 한다.
    앞 순서, 중간 순서 와 후속 적 으로 스 택 의 데이터 구 조 를 사용 해 야 합 니 다. 그들 은 똑 같은 순환 제어 조건 이 있 습 니 다. 즉, 스 택 과 현재 노드 가 모두 비어 있 을 때 순환 을 뛰 어 넘 고 순환 내부 에서 현재 노드 가 비어 있 는 지 에 대해 서도 서로 다른 조작 이 있 습 니 다.
    앞 순 서 를 옮 겨 다 니 기: 현재 결산 점 은 비어 있 지 않 습 니 다. 현재 결산 점 을 현재 결산 점 값 으로 기록 하고 오른쪽 결산 점 을 창고 에 넣 습 니 다. 현재 결산 점 을 왼쪽 아이 로 업데이트 하고 현재 결산 점 이 비어 있 을 때 창고 꼭대기 결산 점 으로 업데이트 합 니 다.
    중간 순서 옮 겨 다 니 기: 현재 결산 점 이 비어 있 지 않 으 면 결산 점 이 창고 에 들 어가 고 왼쪽 아이 로 업 데 이 트 됩 니 다. 현재 결산 점 이 비어 있 을 때 창고 꼭대기 결산 점 으로 업 데 이 트 됩 니 다. 현재 결산 점 값 을 기록 하고 오른쪽 아이 로 업 데 이 트 됩 니 다.
    후 순 옮 겨 다 니 기: 현재 결산 점 이 비어 있 지 않 으 면 결산 점 수 치 를 기록 하고 왼쪽 아이 가 창고 에 들 어가 면 현재 결산 점 은 오른쪽 아이 로 업데이트 되 며 노드 가 비어 있 으 면 창고 꼭대기 결산 점 으로 업 데 이 트 됩 니 다.
    1. 앞 순서 옮 겨 다 니 기
    def pre_order(root):
        """
            
        :param root:        
        :return:       
        """
        stack = []                          #     
        res = []                            #     
        cur = root                          #     
        while stack or cur:                 #                 
            if cur:                         #          
                res.append(cur.val)         #                
                stack.append(cur.right)     #         
                cur = cur.left              #           
            else:                           #         
                cur = stack.pop()           #        
        return res                          #       
    

    2. 중간 순서 옮 겨 다 니 기
    def in_order(root):
        """
            
        :param root:
        :return:
        """
        stack = []                          #     
        res = []                            #     
        cur = root                          #     
        while stack or cur:                 #                 
            if cur:                         #          
                stack.append(cur)           #            
                cur = cur.left              #           
            else:                           #         
                cur = stack.pop()           #        
                res.append(cur.val)         #              
                cur = cur.right             #           
        return res                          #       
    

    3. 후 순 옮 겨 다 니 기
    def post_order(root):
        """
            
        :param root:
        :return:
        """
        stack = []                          #     
        res = []                            #     
        cur = root                          #     
        while stack or cur:                 #                 
            if cur:                         #          
                res.append(cur.val)         #             
                stack.append(cur.left)      #      
                cur = cur.right             #           
            else:                           #         
                cur = stack.pop()           #      
        return res[::-1]                    #         
    

    4. 층 차 를 옮 겨 다 닌 다
    층 차 를 옮 겨 다 니 려 면 대기 열 을 사용 해 야 합 니 다. 매번 결산 점 을 팀 에서 내 보 내 고 이 결산 점 수 치 를 기록 하 며 좌우 아 이 를 순서대로 대열 에 넣 어야 합 니 다. 대기 열 에 결산 점 이 없 을 때 까지.
    def level_order(root):
        if not root:                        #       
            return []                       #      
        res = []                            #     
        cur = root                          #     
        queue = [cur]                       #       
        while queue:                        #        
            cur = queue.pop(0)              #     
            res.append(cur.val)             #       
            if cur.left:                    #         
                queue.append(cur.left)      #      
            if cur.right:                   #         
                queue.append(cur.right)     #      
        return res                          #       
    

    "의" 자형 인쇄 이 진 트 리
    이것 은 이 진 트 리 의 층 차 를 옮 겨 다 니 는 작업 입 니 다. 일반적인 층 차 를 옮 겨 다 니 는 것 과 달리 우 리 는 짝수 줄 이 진 트 리 의 층 결 과 를 역 순 으로 하면 됩 니 다.여기 서 여러분 에 게 이해 하기 쉬 운 방식 을 제공 합 니 다.
    import create_binary_tree                           #                 ,      py      
    
    
    def get_layers(root, switch=True):
        """
               
        :param pRoot:          
        :param switch: “ ”      ,    ,  “ ”    ,           
        :return:       ,           ,          
        """
        if not root:                                #       
            return []                               #      
    
        cur_layer = [root]                          #      
        result = []                                 #     
        right2left = False                          #     ,        
        while cur_layer:                            #         
            cur_val = []                            #      
            next_layer = []                         #      
            for node in cur_layer:                  #            
                cur_val.append(node.val)            #          
                if node.left:                       #          
                    next_layer.append(node.left)    #                
                if node.right:                      #         
                    next_layer.append(node.right)   #             
    
            if right2left:                          #           
                cur_val.reverse()                   #            
    
            if cur_val:                             #              
                result.append(cur_val)              #         
    
            cur_layer = next_layer                  #            
    
            if switch:                              #      “ ”      
                right2left = not right2left         #           
    
        return result                               #       
    
    
    if __name__ == "__main__":
        #     
        s = Solution()
        r = create_binary_tree([1,2,3,4,5,6,7])
        print(get_layers(r))
        #   :[[1], [3, 2], [4, 5, 6, 7]]
    

    여기 서 변수 (right2left) 의 불 값 을 계속 뒤 집어 인접 층 의 인쇄 순서 가 다 르 고 함수 에 스위치 (switch) 를 설정 하여 '의' 자형 인쇄 가 필요 한 지 여 부 를 결정 합 니 다. 독자 들 은 이 스위치 를 닫 으 려 고 시도 할 수 있 습 니 다. 그러면 실험 결 과 는 차원 이 옮 겨 다 니 는 것 과 다 름 없습니다.
    4. 이 진 트 리 의 직렬 화 와 역 직렬 화
    모든 노드 가 정수 인 이 진 트 리 에 대해 우 리 는 하나의 문자열 로 이 나 무 를 대표 할 수 있 습 니 다. 이 과정 은 이 진 트 리 의 직렬 화 라 고 합 니 다. 한 나 무 를 대표 하 는 문자열 서열 에 따라 이 나 무 를 재 구성 하 는 과정 은 이 진 트 리 의 반 직렬 화 입 니 다.직렬 화 와 반 직렬 화 는 서로 역 과정 이 고 이 진 트 리 의 역 주 행 과 이 진 트 리 의 구축 은 서로 역 과정 이다.여 기 는 두 개의 일 치 를 유지 해 야 합 니 다.
    옮 겨 다 니 는 순서 가 일치 합 니 다. 이 진 트 리 를 직렬 화 할 때 앞 순 서 를 옮 겨 다 니 는 방식 을 사용 하면 이 진 트 리 를 재 구성 하려 면 앞 순 서 를 따라 재 구성 해 야 합 니 다.
    주요 문자 대응: 이 진 트 리 의 시공 간 노드 를 '\ #' 로 정렬 하면 이 진 트 리 를 재 구성 할 때 '\ #' 을 만 났 을 때 빈 노드 를 구성 해 야 합 니 다.
    1. 이 진 트 리 의 서열 화
    이 진 트 리 의 직렬 화 과정 은 재 귀 를 사용 하 는 것 이 매우 간단 합 니 다. 우 리 는 재 귀 전 순서 로 옮 겨 다 니 는 방식 으로 실현 할 수 있 습 니 다.
    def serialize(root):
        """
               
        :param root:
        :return:
        """
        if not root:
            return "#"
        return str(root.val) + ',' + serialize(root.left) + ',' + serialize(root.right)
    

    2. 이 진 트 리 의 역 직렬 화
    상기 직렬 화 과정 과 유사 하 게 우 리 는 앞 순 서 를 옮 겨 다 니 는 방식 으로 이 진 트 리 를 재건 한다.
    def deserialize(s):
        """
                
        :param s:
        :return:
        """
        def helper(nodes):
    
            if not nodes:
                return None
    
            val = nodes.pop(0)                  #        
            if val == '#':                      #       “#”
                node = None                     #        
            else:                               #
                node = TreeNode(int(val))       #        
                node.left = helper(nodes)       #      
                node.right = helper(nodes)      #      
    
            return node                         #       
    
        nodes = s.split(',')                     #      
        return helper(nodes)                     #     
    

    5. 이 진 트 리 의 속성
    1. 이 진 트 리 의 최대 깊이
    뿌리 결점 에서 잎 결점 까지 순서대로 지나 가 는 결점 (뿌리, 잎 결점 포함) 은 나무의 한 경 로 를 형성 하고 가장 긴 경로 의 길 이 는 나무의 깊이 이다.이 진 트 리 의 최대 깊이 를 찾 습 니 다.
    이 문 제 는 파워 버튼 에 대응 하 는 문 제 는 [문제 104. 이 진 트 리 의 최대 깊이] 입 니 다. 여기 서 우 리 는 재 귀 법 과 교체 법 두 가지 방식 으로 이 문 제 를 해결 합 니 다.재 귀 법 은 실제 적 으로 모든 결점 이 있 는 차원 의 최대 치 를 얻 는 것 이다.
    def max_depth(root):
        """
                     
        :param root:
        :return:
        """
        if not root:                                #       
            return 0                                #       
        max_left = max_depth(root.left)             #          
        max_right = max_depth(root.right)           #          
        return max(max_left, max_right) + 1         #               ,          
    

    교체 법 은 층 차 를 옮 겨 다 니 는 것 과 유사 하 다. 다만 여 기 는 각 층 의 결점 을 기록 할 필요 가 없고 통계 가 달성 하 는 차원 만 필요 하 다.
    def get_depth(root):
        """
                
        :param root:          
        :return:         
        """
    
        if not root:                                #         
            return 0                                #        
        
        cur_layer = [root]                          #        
        depth = 0                                   #       
        
        while cur_layer:                            #          ,   
            next_layer = []                         #           
            for node in cur_layer:                  #           
                if node.left:                       #            
                    next_layer.append(node.left)    #               
                if node.right:                      #            
                    next_layer.append(node.right)   #               
            cur_layer = next_layer                  #                 
            depth += 1                              #   +1
        return depth                                #       
    

    테스트 용례:
    if __name__ == "__main__":
        r = create_binary_tree([1, 2, 3, 4, 5, 6, 7])
        print(max_depth(r))
        #   :3
    

    2. 이 진 트 리 의 최소 깊이
    최소 깊이 는 뿌리 노드 에서 최근 잎 노드 까지 의 가장 짧 은 경로 의 노드 수량 이다.이 문 제 는 [111. 이 진 트 리 의 최소 깊이] 에서 유래 한 것 으로 해법 은 위의 문제 와 유사 하 다. 여기 서 우 리 는 재 귀적 으로 실현 하고 더욱 편리 하 다.
    def min_depth(root):
        """
                
        :param root:        
        :return:         
        """
        if not root:                                            #       
            return 0                                            #        
        left_min_depth = min_depth(root.left)                   #                
        right_min_depth = min_depth(root.right)                 #                
        if left_min_depth > 0 and right_min_depth > 0:          #              0
            res = min(left_min_depth, right_min_depth) + 1      #                +1
        else:                                                   #          
            res = max(left_min_depth, right_min_depth) + 1      #                ,   +1
        return res
    

    테스트 용례:
    if __name__ == "__main__":
        r = create_binary_tree([1, 2, 3, 4, 5, 6, 7])
        print(min_depth(r))
        #   :3
    

    3. 모든 경로
    이 문제 의 출처 [257. 이 진 트 리 의 모든 경로] 는 구체 적 인 해법 을 볼 수 있 습 니 다.
    def get_paths(root):
        """
           root             
        :type root:    
        :rtype:     ,        
        """
        def helper(root, path, res):
            """
              
            :param root:    
            :param path:    root       
            :param res:     
            :return:
            """
            cur_path = path + [root.val]            #     
            if not root.left and not root.right:    #          
    
                res.append(cur_path)                #         
                return                              #   
    
            if root.left:                           #        
                helper(root.left, cur_path, res)    #      
            if root.right:                          #        
                helper(root.right, cur_path, res)   #      
    
        if not root:                                #       
            return []                               #      ,     
    
        paths = []                                  #     
        helper(root, [], paths)                     #     
    
        return paths                                #     
    

    테스트 용례:
    if __name__ == "__main__":
        r = create_binary_tree([1, 2, 3, 4, 5, 6, 7])
        print(min_depth(r))
        #   :[[1, 2, 4], [1, 2, 5], [1, 3, 6], [1, 3, 7]]
    

    4. 대칭 이 진 트 리
    이 문 제 는 [101. 대칭 이 진 트 리] 에서 유래 하여 함수 로 이 진 트 리 가 미 러 이 진 트 리 인지 아 닌 지 를 판단 합 니 다.좌우 자목 거울 이 대칭 적 이면 이 진 트 리 도 대칭 적 이다.
    def isSymmetric(root):
        """
                  
        :param root:
        :return:
        """
        def is_mirror(p, q):                        #             
            if not p and not q:                     #          
                return True                         #     
            elif not p and q or p and not q:        #             
                return False                        #      
            else:                                   #           
                #           :      ,             ,             
                return p.val == q.val and is_mirror(p.left, q.right) and is_mirror(p.right, q.left)
    
        return is_mirror(root, root)                #              
    

    테스트 용례:
    if __name__ == '__main__':
        r = create_binary_tree([1, 2, 3, 4, 5, 6, 7])
        print(is_symmetric(r))
        #     :False
    

    5. 이 진 트 리 조작
    1. 이 진 트 리 의 거울
    두 갈래 나 무 를 거울 두 갈래 나무 로 바꾸다.뿌리 노드 의 좌우 자 나 무 를 교환 한 후 좌우 자 나 무 를 거울 나무 로 바 꾸 면 된다.
    def mirror(root):
        """
              
        :param root:
        :return:
        """
        if root:
            root.left, root.right = root.right, root.left   #       
            mirror(root.left)                               #       
            mirror(root.right)
    

    테스트 용례:
    if __name__ == '__main__':
        r = create_binary_tree([1, 2, 3, 4, 5, 6, 7])
        print(get_layers(r, False))    #     “ ”           
        mirror(r)
        print(get_layers(r, False))
        #     :[[1], [2, 3], [4, 5, 6, 7]], [[1], [3, 2], [7, 6, 5, 4]]
    

    6. 통합
    우 리 는 상기 코드 를 통합 하여 실례 화 된 이 진 트 리 를 구축 합 니 다.
    class BinaryTree:
        def __init__(self, node_vals):
            self.tree = create_binary_tree(node_vals)
    
        @staticmethod                   #     
        def create_binary_tree(nodes):
            def helper(node, i):
                if i < len(nodes):
                    if nodes[i] in ['#', None]:
                        return None
                    else:
                        node = TreeNode(nodes[i])
                        node.left = helper(node.left, 2 * i + 1)
                        node.right = helper(node.right, 2 * i + 2)
                        return node
                return node
            root = TreeNode(0)
            root = helper(root, 0)
            return root
    
        #        
        @property
        def serialize(self):
            s = lambda r: str(r.val) + ',' + s(r.left) + ',' + s(r.right) if r else "#"
            return s(self.tree)
    
        #         ,       
        @property
        def pre_order(self):
            helper = lambda n: [n.val] + helper(n.left) + helper(n.right) if n else []
            return helper(self.tree)
    
        #         ,       
        @property
        def in_order(self):
            helper = lambda n: helper(n.left) + [n.val] + helper(n.right) if n else []
            return helper(self.tree)
    
        #         ,       
        @property
        def post_order(self):
            helper = lambda n: helper(n.left) + helper(n.right) + [n.val] if n else []
            return helper(self.tree)
    
        #     ,         
        @property
        def level_order(self):
            def helper(node, level):
                if not node:
                    return
                else:
                    res[level - 1].append(node.val)
                    if len(res) == level:
                        res.append([])
                    helper(node.left, level + 1)
                    helper(node.right, level + 1)
    
            res = [[]]
            helper(self.tree, 1)
            return res[:-1]
    
        #           
        @property
        def max_depth(self):
            helper = lambda r: max(helper(r.left), helper(r.right))+1 if r else 0
            return helper(self.tree)
    
        #           
        @property
        def min_depth(self):
            def helper(root):
                if not root:
                    return 0
                left_min_depth = helper(root.left)
                right_min_depth = helper(root.right)
                if left_min_depth > 0 and right_min_depth > 0:
                    res = min(left_min_depth, right_min_depth) + 1
                else:
                    res = max(left_min_depth, right_min_depth) + 1
                return res
            return helper(self.tree)
    
        #           
        @property
        def all_paths(self):
            def helper(root, path, res):
                cur_path = path + [root.val]
                if not root.left and not root.right:
                    res.append(cur_path)
                    return
                if root.left:
                    helper(root.left, cur_path, res)
                if root.right:
                    helper(root.right, cur_path, res)
            if not self.tree:
                return []
            paths = []
            helper(self.tree, [], paths)
            return paths
    
        #            
        @property
        def is_symmetric(self):
            def helper(p, q):
                if not p and not q:
                    return True
                elif not p and q or p and not q:
                    return False
                else:
                    return p.val == q.val and helper(p.left, q.right) and helper(p.right, q.left)
            return helper(self.tree, self.tree)
    
        #         
        def flip(self):
            def helper(root):
                if root:
                    root.left, root.right = root.right, root.left
                    helper(root.left)
                    helper(root.right)
            helper(self.tree)
    

    장식 부호 @ property 는 클래스 속성 을 표시 합 니 다. 테스트 용례 는:
    if __name__ == '__main__':
        nodes = [1, 2, 3, 4, 5, 6, 7, 8]
        print('       ,      :{}.'.format(nodes))
        bt = BinaryTree(nodes)
        print('          :{}'.format(bt.serialize))
        print('           :{}'.format(bt.pre_order))
        print('           :{}'.format(bt.in_order))
        print('           :{}'.format(bt.post_order))
        print('           :{}'.format(bt.level_order))
        print('           :{}'.format(bt.max_depth))
        print('           :{}'.format(bt.min_depth))
        print('           :{}'.format(bt.all_paths))
        print('         :{}'.format(bt.is_symmetric))
        print('        ')
        bt.flip()
        print('              :{}'.format(bt.level_order))
    

    이 이 진 트 리 [1, 2, 3, 4, 5, 6, 7, 8] 는 실제로:
          1
         / \ 
        2   3
       / \ / \
      4  5 6  7
     /
    8
    

    테스트 결 과 는:
              :1,2,4,8,#,#,#,5,#,#,3,6,#,#,7,#,#
               :[1, 2, 4, 8, 5, 3, 6, 7]
               :[8, 4, 2, 5, 1, 6, 3, 7]
               :[8, 4, 5, 2, 6, 7, 3, 1]
               :[[1], [2, 3], [4, 5, 6, 7], [8]]
               :4
               :3
               :[[1, 2, 4, 8], [1, 2, 5], [1, 3, 6], [1, 3, 7]]
             :False
            
                  :[[1], [3, 2], [7, 6, 5, 4], [8]]
    

    질문 이나 조언 이 있 으 시 면 댓 글 남 겨 주세요 ~

    좋은 웹페이지 즐겨찾기