Go Tour Exercise: Equivalent Binary Trees

前端 未结 23 1640
攒了一身酷
攒了一身酷 2020-12-12 23:39

I am trying to solve equivalent binary trees exercise on go tour. Here is what I did;

package main

import \"tour/tree\"
import \"fmt\"

// Walk walks the tr         


        
相关标签:
23条回答
  • 2020-12-13 00:34

    Haven't seen it so far in this thread. I used the nil channel technique presented in just for func

    The issue with closing the channels was solved by kicking them off in an goroutine iife.

    I think I could check more performant for equality though.

    package main
    
    import (
        "fmt"
        "reflect"
        "sort"
    
        "golang.org/x/tour/tree"
    )
    
    // Walk walks the tree t sending all values
    // from the tree to the channel ch.
    func Walk(t *tree.Tree, ch chan int) {
        ch <- t.Value
        if t.Right != nil {
            Walk(t.Right, ch)
        }
        if t.Left != nil {
            Walk(t.Left, ch)
        }
    
    }
    
    // Same determines whether the trees
    // t1 and t2 contain the same values.
    func Same(t1, t2 *tree.Tree) bool {
    
        c1 := make(chan int)
        s1 := []int{}
    
        go func() {
            Walk(t1, c1)
            close(c1)
        }()
    
        c2 := make(chan int)
        s2 := []int{}
    
        go func() {
            Walk(t2, c2)
            close(c2)
        }()
    
        for c1 != nil || c2 != nil {
            select {
            case v, ok := <-c1:
                if !ok {
                    c1 = nil
                    sort.Ints(s1)
                    continue
                }
                s1 = append(s1, v)
            case v, ok := <-c2:
                if !ok {
                    c2 = nil
                    sort.Ints(s2)
                    continue
                }
                s2 = append(s2, v)
            }
        }
        return reflect.DeepEqual(s1, s2)
    }
    
    func main() {
        fmt.Println(Same(tree.New(1), tree.New(1)))
    }
    
    0 讨论(0)
  • 2020-12-13 00:35

    You could use close() if your Walk function doesn't recurse on itself. i.e. Walk would just do:

    func Walk(t *tree.Tree, ch chan int) {
        walkRecurse(t, ch)
        close(ch)
    }
    

    Where walkRecurse is more or less your current Walk function, but recursing on walkRecurse. (or you rewrite Walk to be iterative - which, granted, is more hazzle) With this approach, your Same() function have to learn that the channels was closed, which is done with the channel receive of the form

    k, ok1 := <-ch
    g, ok2 := <-ch
    

    And take proper action when ok1 and ok2 are different, or when they're both false

    Another way, but probably not in the spirit of the exercise, is to count the number of nodes in the tree:

    func Same(t1, t2 *tree.Tree) bool {
        countT1 := countTreeNodes(t1)
        countT2 := countTreeNodes(t2)
        if countT1 != countT2 {
            return false
        }
        ch1 := make(chan int)
        ch2 := make(chan int)
        go Walk(t1, ch1)
        go Walk(t2, ch2)
        for i := 0; i < countT1; i++ {
            if <-ch1 != <-ch2 {
                return false
            }
        }
        return true
    }
    

    You'll have to implement the countTreeNodes() function, which should count the number of nodes in a *Tree

    0 讨论(0)
  • 2020-12-13 00:35

    All of previous answers do not solve the task about Same function. The question is:

    // Same determines whether the trees
    // t1 and t2 contain the same values.
    func Same2(t1, t2 *tree.Tree) bool
    

    It shouldn't consider structure of tree. That's why following tests fail, gives us false in both lines:

    fmt.Println("Should return true:", Same(tree.New(1), tree.New(1)))
    fmt.Println("Should return false:", Same(tree.New(1), tree.New(2)))
    

    Remember?

    The function tree.New(k) constructs a randomly-structured (but always sorted) binary tree holding the values k, 2k, 3k, ..., 10k.

    You need just check that both trees have the same values. And task description clearly notice that:

    Same(tree.New(1), tree.New(1)) should return true, and Same(tree.New(1), tree.New(2)) should return false.

    So to solve the task you need buffer all results from one tree and check does the values from second tree are in the first one.

    Here is my solution, it's not ideal one :) :

    // Same determines whether the trees
    // t1 and t2 contain the same values.
    func Same(t1, t2 *tree.Tree) bool {
        ch1, ch2 := make(chan int), make(chan int)
        go Walk(t1, ch1)
        go Walk(t2, ch2)
    
        var tv1 = []int{}
    
        for v := range ch1 {
            tv1 = append(tv1, v)
        }
    
        inArray := func(arr []int, value int) bool {
            for a := range arr {
                if arr[a] == value {
                    return true
                }
            }
            return false
        }
    
        for v2 := range ch2 {
            if !inArray(tv1, v2) {
                return false
            }
        }
    
        return true
    }
    
    0 讨论(0)
  • 2020-12-13 00:36

    For whoever interested, if you wonder how to solve this without creating a separate recursive function, here is an answer using a stack:

    func Walk(t *tree.Tree, ch chan int) {
        defer close(ch)
        visitStack := []*tree.Tree{t}
        visited := make(map[*tree.Tree]bool, 1)
        for len(visitStack) > 0 {
            var n *tree.Tree
            n, visitStack = visitStack[len(visitStack)-1], visitStack[:len(visitStack)-1]
            if visited[n] {
                ch <- n.Value
                continue
            }
            if n.Right != nil {
                visitStack = append(visitStack, n.Right)
            }
            visitStack = append(visitStack, n)
            if n.Left != nil {
                visitStack = append(visitStack, n.Left)
            }
            visited[n] = true
        }
    }
    
    0 讨论(0)
  • 2020-12-13 00:38

    This is my solution. It properly checks for differences in the length of the two sequences.

    package main
    
    import "code.google.com/p/go-tour/tree"
    import "fmt"
    
    func Walk(t *tree.Tree, ch chan int) {
        var walker func (t *tree.Tree)
        walker = func (t *tree.Tree) {
            if t.Left != nil {
                walker(t.Left)
            }
            ch <- t.Value
            if t.Right != nil {
                walker(t.Right)
            }
        }
        walker(t)
        close(ch)
    }
    
    func Same(t1, t2 *tree.Tree) bool {
        chana := make (chan int)
        chanb := make (chan int)
    
        go Walk(t1, chana)
        go Walk(t2, chanb)
    
        for {
            n1, ok1 := <-chana
            n2, ok2 := <-chanb        
            if n1 != n2 || ok1 != ok2 {
                return false
            }
            if (!ok1) {
                break
            }
        }
        return true; 
    }
    
    0 讨论(0)
提交回复
热议问题