• 初识go语言,写了个递归题目作为helloworld


    上周D总在公司TTT上普及了go,当时只是概念上知道这门语言,D总出的小题目我用Java写了类似于DP的算法,被宣布太耗内存^^。这两天在公交上看了会reference(http://golang.org),最喜欢的特性是goroutines、多返回值和并列赋值/声明。觉得光看没用,还是写个helloworld吧,想到之前看到过一个这样的题目:

    一颗二叉树,其节点上不均匀的分布了若干石头,石头数跟二叉树总节点数相同,石头只能在边上(即父子节点之间)进行搬运,每次只能搬运一颗石头。求使每个节点石头皆为一的最少搬运次数。

    题目思路不多说了,甚至可能我的解法不是最优,这里主要是作为golang练手,在代码里详述。由于连机器上都还没装go环境,直接在http://play.golang.org上写的:

      1 package main
      2 
      3 import (
      4     "fmt"
      5 )
      6 
      7 var N int = 9
      8 var moves int = 0
      9 
     10 type Node struct {
     11     V int        // number of stones the node keep
     12     Feel int    // number of stones the tree have, can be positive or negative
     13     L *Node        // left child
     14     R *Node        // right child
     15 }
     16 
     17 func (node *Node) String() string {
     18     return fmt.Sprintf("{%d|%d}", node.V, node.Feel)
     19 } 
     20 
     21 /**
     22     what the mokced tree seems like:
     23      0|1
     24     / \
     25    1|3 2|1
     26   / \   \
     27  3|0 4|1 5|0
     28   \     / \
     29    6|1 7|0 8|2
     30 */
     31 func mock() *Node {
     32     // make new nodes
     33     nodes := make([]*Node, N)
     34     nodes[0] = &Node{1,0,nil,nil}
     35     nodes[1] = &Node{3,0,nil,nil}
     36     nodes[2] = &Node{1,0,nil,nil}
     37     nodes[3] = &Node{0,0,nil,nil}
     38     nodes[4] = &Node{1,0,nil,nil}
     39     nodes[5] = &Node{0,0,nil,nil}
     40     nodes[6] = &Node{1,0,nil,nil}
     41     nodes[7] = &Node{0,0,nil,nil}
     42     nodes[8] = &Node{2,0,nil,nil}
     43 
     44     // construct tree    
     45     nodes[0].L, nodes[0].R = nodes[1], nodes[2]
     46     nodes[1].L, nodes[1].R = nodes[3], nodes[4]    
     47     nodes[2].L, nodes[2].R = nil, nodes[5]
     48     nodes[3].L, nodes[3].R = nil, nodes[6]
     49     nodes[4].L, nodes[4].R = nil, nil
     50     nodes[5].L, nodes[5].R = nodes[7], nodes[8]
     51     nodes[6].L, nodes[6].R = nil, nil
     52     nodes[7].L, nodes[7].R = nil, nil
     53     nodes[8].L, nodes[8].R = nil, nil
     54     return nodes[0]
     55 }
     56 
     57 /**
     58  move stones between root, root.L, root.R, recursively.
     59 */
     60 func move(root *Node) {
     61     moves = 0
     62     print("init", root)
     63     count(root)
     64     print("after count", root)
     65     collect(root)
     66     print("after collect", root)
     67     welfare(root)
     68     print("after welfare, finally got", root)
     69     fmt.Println("all stone moves: ", moves)
     70 }
     71 
     72 /**
     73  count feel of stones and number of nodes of root.
     74 */
     75 func count(root *Node) (feel int) {
     76     if root == nil {
     77         return 0 
     78     }
     79     feelL := count(root.L)
     80     feelR := count(root.R)
     81     root.Feel = feelL + feelR + root.V - 1
     82     return root.Feel
     83 }
     84 
     85 /**
     86   collect redundant stones up from rich child(ren)
     87 */
     88 func collect(root *Node) {
     89     if root == nil {
     90         return
     91     }
     92     collect(root.L)
     93     collect(root.R)
     94     if root.L != nil && root.L.Feel > 0 {
     95         // todo: number of stones to collect
     96         todo := root.L.Feel
     97         moves += todo
     98         // move upward
     99         root.V += todo
    100         root.L.Feel = 0
    101         root.L.V -= todo
    102     }
    103     if root.R != nil && root.R.Feel > 0 {
    104         todo := root.R.Feel
    105         moves += todo
    106         root.V += todo
    107         root.R.Feel = 0
    108         root.R.V -= todo
    109     }
    110 }
    111 
    112 /**
    113   dispatch all stones collected to poor child(ren)
    114 */
    115 func welfare(root *Node) {
    116     if root == nil {
    117         return
    118     }
    119     if root.L != nil && root.L.Feel < 0 {
    120         todo := -root.L.Feel
    121         root.L.Feel = 0
    122         root.L.V += todo
    123         root.Feel = 0 
    124         root.V -= todo
    125         moves += todo
    126     }
    127     if root.R != nil && root.R.Feel < 0 {
    128         todo := -root.R.Feel
    129         root.R.Feel = 0
    130         root.R.V += todo
    131         root.Feel = 0
    132         root.V -= todo
    133         moves += todo
    134     }
    135     welfare(root.L)
    136     welfare(root.R)
    137 }
    138 
    139 /**
    140  bfs print using chan as queue
    141 */
    142 func print(title string, root *Node) {
    143     fmt.Println("==========| ", title, " |==========");
    144     queue := make(chan *Node, N)
    145     queue <- root
    146     i := 0
    147     for node := range queue {
    148         fmt.Print(node, "; ")
    149         if node.L != nil {
    150             queue <- node.L
    151         }
    152         if node.R != nil {
    153             queue <- node.R
    154         }
    155         if i += 1; i == N {
    156             close(queue)
    157             break
    158         }
    159     }
    160     fmt.Println()
    161 }
    162 
    163 func main() {
    164     move(mock())
    165 }

    其中最自我感觉良好的是,自己想到了个主意用chan作为queue把二叉树BFS打印出来^^,虽然这个在熟手们可能是常用做法。

    代码里略写了些注释。

    如果:

    1. 思路/逻辑不正确;
    2. 还有比这更优化的解法;
    3. 有些代码不符合go规范或约定;

    请不吝点评:D

     

  • 相关阅读:
    hadoop yarn日志分离
    hadoop优化
    hive UDF
    hadoophttpfs
    spark编译
    spark feature
    python
    python 装饰器
    HTML特殊转义字符列表
    博客园数据统计
  • 原文地址:https://www.cnblogs.com/leoyonn/p/2836653.html
Copyright © 2020-2023  润新知