Finding size of max independent set in binary tree - why faulty “solution” doesn't work?

后端 未结 2 1552
小鲜肉
小鲜肉 2021-01-23 08:54

Here is a link to a similar question with a good answer: Java Algorithm for finding the largest set of independent nodes in a binary tree.

I came up with a different ans

相关标签:
2条回答
  • 2021-01-23 09:38

    Interjay has noted why your answer is incorrect. The problem can be solved with a recursive algorithm find-max-independent which, given a binary tree, considers two cases:

    1. What is the max-independent set given that the root node is included?
    2. What is the max-independent set given that the root node is not included?

    In case 1, since the root node is included, neither of its children can. Thus we sum the value of find-max-independent of the grandchildren of root, plus the value of root (which must be included), and return that.

    In case 2, we return the max value of find-max-independent of the children nodes, if any (we can pick only one)

    The algorithm may look something like this (in python):

    def find_max_independent ( A ):
        N=len(A)
    
        def children ( i ):
            for n in (2*i+1, 2*i+2):
                if n<N: yield n
    
        def gchildren ( i ):
            for child in children(i):
                for gchild in children(child):
                    yield gchild
    
        memo=[None]*N
    
        def rec ( root ):
            "finds max independent set in subtree tree rooted at root. memoizes results"
    
            assert(root<N)
    
            if memo[root] != None:
                return memo[root]
    
            # option 'root not included': find the child with the max independent subset value
            without_root = sum(rec(child) for child in children(root))
    
            # option 'root included': possibly pick the root
            # and the sum of the max value for the grandchildren
            with_root =  max(0, A[root]) + sum(rec(gchild) for gchild in gchildren(root))
    
            val=max(with_root, without_root)
            assert(val>=0)
            memo[root]=val
    
            return val
    
    
        return rec(0) if N>0 else 0
    

    Some test cases illustrated:

    tests=[
        [[1,2,3,4,5,6], 16], #1
        [[-100,2,3,4,5,6], 6], #2
        [[1,200,3,4,5,6], 200], #3
        [[1,2,3,-4,5,-6], 6], #4
        [[], 0],
        [[-1], 0],
    ]
    
    for A, expected in tests:
        actual=find_max_independent(A)
        print("test: {}, expected: {}, actual: {} ({})".format(A, expected, actual, expected==actual))
    

    Sample output:

    test: [1, 2, 3, 4, 5, 6], expected: 16, actual: 16 (True)
    test: [-100, 2, 3, 4, 5, 6], expected: 15, actual: 15 (True)
    test: [1, 200, 3, 4, 5, 6], expected: 206, actual: 206 (True)
    test: [1, 2, 3, -4, 5, -6], expected: 8, actual: 8 (True)
    test: [], expected: 0, actual: 0 (True)
    test: [-1], expected: 0, actual: 0 (True)
    

    Test case 1

    Test case 2

    Test case 3

    Test case 4

    The complexity of the memoized algorithm is O(n), since rec(n) is called once for each node. This is a top-down dynamic programming solution using depth-first-search.

    (Test case illustrations courtesy of leetcode's interactive binary tree editor)

    0 讨论(0)
  • 2021-01-23 09:45

    Your algorithm doesn't work because the set of nodes it returns will be either all from odd levels, or all from even levels. But the optimal solution can have nodes from both.

    For example, consider a tree where all weights are 0 except for two nodes which have weight 1. One of these nodes is at level 1 and the other is at level 4. The optimal solution will contain both these nodes and have weight 2. But your algorithm will only give one of these nodes and have weight 1.

    0 讨论(0)
提交回复
热议问题