I'm learning Go to prepare for a coding interview, and there's a leetcode question for tree traversal. It works with recursion in Python, but Golang behaves differently.
I notice the elements in the res slice gets cleared one by one when every call stack is popped.
The original question is
The result should be [1,3,5,6,2,4], and it was returned correctly in Python, but the following Go code returns []
/**
* Definition for a Node.
* type Node struct {
* Val int
* Children []*Node
* }
*/
func preorder(root *Node) []int {
res := []int{}
traverse(root, res)
return res
}
func traverse(root *Node, res []int){
if root == nil{
return
}
res = append(res, root.Val)
for _, n := range root.Children{
traverse(n, res)
}
// the last element is removed from the slice every time when the code execution reaches here
}
------------------------------------- updates --------------------------------------
Thanks for all your answers, now I think I have a better understanding of how slice works in Go
The following code works for me now:
/**
* Definition for a Node.
* type Node struct {
* Val int
* Children []*Node
* }
*/
func preorder(root *Node) []int {
res := []int{}
res = traverse(root, res)
return res
}
func traverse(root *Node, res []int) []int{
if root == nil{
return res
}
res = append(res, root.Val)
for _, n := range root.Children{
res = traverse(n, res)
}
return res
}
you can consider passing the res as a pointer *[]int instead so that the values get updated to the same slice else you are just passing a copy of it.
In your terminating case, you're not returning the accumulator:
if root == nil{
return
}
But...
I would use a closure so as to avoid cloning the slice on every recursive call (Go passes by value):
type Node struct {
Val int
Children []*Node
}
func preorder(root *Node) (res []int) {
var traverse func(*Node)
traverse = func(root *Node) {
if root != nil {
res = append(res, root.Val)
for _, n := range root.Children {
traverse(n)
}
}
}
traverse(root)
return res
}
Related
So I am trying to retrieve a node in a minheap tree by index. The way that it would be called is that I would intiatate a empty MinHeapNode struct and pass by its value via &node so that between recursive function calls, if a match was found it would then return. However it seems that even given a found result the newly assigned empty node would be overwritten by another recursive call that has an empty version of that node. I'm still getting used to the idea of pointers and addresses so I believed that passing the values address would get around this since it would be calling the same value at the same address between calls. But apparently this is something is not correct.
type MinHeapNode struct {
Parent *MinHeapNode
Left *MinHeapNode
Right *MinHeapNode
Value int
Index int
}
func (MHN *MinHeapNode) Insert(value int) {
if !MHN.hasLeftChild() {
MHN.Left = &MinHeapNode{Parent: MHN, Value: value}
return
}
if !MHN.hasRightChild() {
MHN.Right = &MinHeapNode{Parent: MHN, Value: value}
return
}
if MHN.hasLeftChild(){
MHN.Left.Insert(value)
return
}
if MHN.hasRightChild(){
MHN.Right.Insert(value)
return
}
}
func (MHN *MinHeapNode) setIndex(count *int){
index := *count
*count = *count +1
MHN.Index = index
if MHN.hasLeftChild(){
MHN.Left.setIndex(count)
}
if MHN.hasRightChild(){
MHN.Right.setIndex(count)
}
}
func (MHN *MinHeapNode) getIndex(index int, node *MinHeapNode){
if MHN == nil{
return
}
if MHN.Index == index{
node = MHN
return
}
MHN.Left.getIndex(index, node)
MHN.Right.getIndex(index,node)
}
}
type MinHeapTree struct {
Root MinHeapNode
Size int
}
func (MHT *MinHeapTree) getIndex(index int)(*MinHeapNode, error){
if MHT.Size < index +1 {
err := fmt.Errorf("index exceeds tree size")
return nil, err
}
var node MinHeapNode
MHT.Root.getIndex(index, &node)
return &node, nil
}
The issue you are facing appears to be with the statement node = MHN in getIndex (but as your code is incomplete I cannot confirm if this is the only issue).
node = MHN will update the value of node (a parameter, so passed by value and, its scope is the function body). This has no impact on the value of the MinHeapNode that node pointed to at the start of the function. To correct this use *node = *MHN.
This can be demonstrated with a simple program (playground)
type MinHeapNode struct {
Test string
}
func getIndexBad(node *MinHeapNode) {
newNode := MinHeapNode{Test: "Blah"}
node = &newNode
}
func getIndexGood(node *MinHeapNode) {
newNode := MinHeapNode{Test: "Blah"}
*node = newNode
}
func main() {
n := MinHeapNode{}
fmt.Println(n)
getIndexBad(&n)
fmt.Println(n)
getIndexGood(&n)
fmt.Println(n)
}
The output demonstrates that the "bad" function does not update the passed in node:
{}
{}
{Blah}
I have a single linked list. how do I get the length of the linked list with a recursive method that had a pointer receiver?
type Node struct {
data int
next *Node
}
I had tried like this, but always return 1
func (n *Node) recursiveLength() (result int) {
if n != nil {
result += 1
n = n.next
}
return
}
Your solution is not recursive. It's have compilation error. But if we want to fix it it could be like this:
package main
import "fmt"
type Node struct {
data int
next *Node
}
func (n *Node) recursiveLength() (result int) {
if n != nil {
result += 1
n = n.next
return result + n.recursiveLength()
}
return 0
}
func main() {
x := Node{data: 0, next: &Node{data: 1, next: &Node{data: 2, next: nil}}}
fmt.Println(x.recursiveLength())
}
But this is not a good idea to write length method, It's better to change it to a function that accepts a Node and returns its length:
package main
import "fmt"
type Node struct {
data int
next *Node
}
func recursiveLength(n *Node) (result int) {
if n != nil {
n = n.next
return 1 + recursiveLength(n)
}
return 0
}
func main() {
x := Node{data: 0, next: &Node{data: 1, next: &Node{data: 2, next: nil}}}
fmt.Println(recursiveLength(&x))
}
I want to remove a Node from a linked list in Go, and I have this struct and these methods:
type Node struct {
Next *Node
Val int
}
func (n *Node) Append(val int) {
end := &Node{Val: val}
here := n
for here.Next != nil {
here = here.Next
}
here.Next = end
}
func Remove(n *Node, val int) *Node {
head := n
for head.Next != nil {
if head.Next.Val == val {
head.Next = head.Next.Next
return head
}
head = head.Next
}
return head
}
func NewNode(val int) *Node {
return &Node{Val: val}
}
I want to remove an item like this:
n := NewNode(1)
n.Append(2)
n.Append(3)
n.Append(4)
n.Append(5)
m := Remove(n, 3)
for m != nil {
fmt.Println(n.Val)
m = m.Next
}
The items that get printed out are 3 and 5, not 1,2,4and5`. I re-implemented this code in Python and got the expected answer. What is going on in Go? I have a feeling it has to do something with pointers.
You lose the head from returning a node you use to traverse. Also you are printing out the wrong object
type Node struct {
Next *Node
Val int
}
func (n *Node) Append(val int) {
end := &Node{Val: val}
here := n
for here.Next != nil {
here = here.Next
}
here.Next = end
}
func Remove(n *Node, val int) *Node {
traverser := n
for traverser.Next != nil {
if traverser.Next.Val == val {
traverser.Next = traverser.Next.Next
return n
}
traverser = traverser.Next
}
return n
}
func NewNode(val int) *Node {
return &Node{Val: val}
}
func main() {
n := NewNode(1)
n.Append(2)
n.Append(3)
n.Append(4)
n.Append(5)
m := Remove(n, 3)
for m != nil {
fmt.Println(m.Val)
m = m.Next
}
}
I want to make a linked list which can hold the values of any type but the linked list must hold values of any one type only.
In general when I am using interfaces for achieving this - any type which implements the interface for the node can be added to the linked list.
I have written an implementation for this where whenever a new key is added to the linked list, the type of the key is checked against the type of the key at the head. I want to understand if this is the correct way of implementing it or is there a better way of doing it.
package main
import (
"errors"
"fmt"
"reflect"
"strings"
)
type MyNode struct {
value int
}
func (node *MyNode) PrintValue() {
fmt.Printf(" %d ", node.value)
}
type llNode struct {
key llNodeInterface
next *llNode
llNodeType reflect.Type
}
type llNodeInterface interface {
PrintValue()
}
type ComplexNode struct {
realValue int
imageValue int
}
func (node *ComplexNode) PrintValue() {
fmt.Printf(" %d + i%d", node.realValue, node.imageValue)
}
// Student type.
type Student struct {
name string
age int
}
// Student implements the PrintValue function - thus llNodeInterface is implemented.
func (node *Student) PrintValue() {
fmt.Printf("Name: %s | Age : %d ", node.name, node.age)
}
// Function which will check the of the new node before adding to the linked
// list. It checks the type of the new key against the type of the key in the
// head. If both are equal then it proceed else return error.
func (head *llNode) AddBeforeHeadTypeCheck(passedKey llNodeInterface) error {
if head.key == nil {
head.key = passedKey
head.llNodeType = reflect.TypeOf(head.key)
} else {
typeOfPassedKey := reflect.TypeOf(passedKey)
if typeOfPassedKey != head.llNodeType {
fmt.Printf("\nUnsupported type for the type %T", passedKey)
return errors.New("Type mistmatch")
}
temp := llNode{key: head.key, next: head.next}
head.key = passedKey
head.next = &temp
}
return nil
}
// Function which will not check the types and will simply add the new node to
// the linked list. Thus linked list will be able to have nodes of multiple
// types.
func (head *llNode) AddBeforeHead(passedKey llNodeInterface) {
if head.key == nil {
head.key = passedKey
head.llNodeType = reflect.TypeOf(head.key)
} else {
temp := llNode{key: head.key, next: head.next}
head.key = passedKey
head.next = &temp
}
}
func (head *llNode) Init() {
head.key = nil
head.next = nil
head.llNodeType = nil
}
// Print the linked list.
func (head *llNode) DisplayLL() {
temp := head
fmt.Printf("\n%s", strings.Repeat("#", 80))
fmt.Printf("\nPrinting the linked list\n")
for {
if temp.key == nil {
fmt.Println("Linked list is empty")
break
} else {
fmt.Printf("\n %T %v ", temp.key, temp.key)
key := temp.key
key.PrintValue()
if temp.next == nil {
break
} else {
temp = temp.next
}
}
}
fmt.Printf("\n%s", strings.Repeat("#", 80))
fmt.Printf("\n\n")
}
func testWithMixedType() {
head := llNode{}
head.Init()
for i := 1; i < 10; i++ {
temp := &ComplexNode{i, i * 10}
head.AddBeforeHeadTypeCheck(temp)
}
temps := &Student{"rishi", 20}
head.AddBeforeHeadTypeCheck(temps) // Will give error.
head.DisplayLL()
}
func testWithComplexNumber() {
head := llNode{}
head.Init()
for i := 1; i < 10; i++ {
temp := &ComplexNode{i, i * 10}
head.AddBeforeHeadTypeCheck(temp)
}
}
func main() {
testWithComplexNumber()
testWithMixedType()
}
The code is working fine - but I want to understand if there is a better or different way of doing this.
Also - what is the performance impact of the current checking of types using the reflect package. Is there a different way of achieving the same thing.
Unsupported type for the type *main.Student
Unsupported type for the type *main.Student
################################################################################
Printing the linked list
*main.ComplexNode &{9 90} 9 + i90
*main.ComplexNode &{8 80} 8 + i80
*main.ComplexNode &{7 70} 7 + i70
*main.ComplexNode &{6 60} 6 + i60
*main.ComplexNode &{5 50} 5 + i50
*main.ComplexNode &{4 40} 4 + i40
*main.ComplexNode &{3 30} 3 + i30
*main.ComplexNode &{2 20} 2 + i20
*main.ComplexNode &{1 10} 1 + i10
################################################################################
Good news, starting from Go 1.18, Generics are now supported in Go.
Following the example from the question, here is a simplified LinkedList using Generics. You can tinker with it at the playground here.
package main
import "fmt"
type MyNode[T any] struct {
next *MyNode[T]
value T
}
type MyLinkedList[T any] struct {
head *MyNode[T]
tail *MyNode[T]
}
func (list *MyLinkedList[T]) Add(t T) *MyLinkedList[T] {
// create node
node := &MyNode[T]{nil, t}
// if first node in list
if list.head == nil {
list.head = node
list.tail = node
} else {
list.tail.next = node
list.tail = list.tail.next
}
return list
}
func (list *MyLinkedList[T]) AddBeforeHead(t T) *MyLinkedList[T] {
node := &MyNode[T]{nil, t}
if list.head != nil {
node.next = list.head
list.head = node
} else {
// make head
list.head = node
list.tail = node
}
return list
}
// display the list
func DisplayList[T any](list *MyLinkedList[T]) string {
var out string = ""
iter := list.head
for iter != nil {
out += fmt.Sprintf("%v -> ", iter.value)
iter = iter.next
}
return out
}
func (list *MyLinkedList[T]) Display() string {
return DisplayList(list)
}
// for printing node value
// you could also implement Stringer
// but this is besides the point, you can ignore
func (node *MyNode[T]) String() string {
return fmt.Sprintf("<MyNode: %v>", node.value)
}
// helper func: create list from array
func CreateLinkedList[T any](arr []T) *MyLinkedList[T] {
list := &MyLinkedList[T]{}
for _, v := range arr {
list.Add(v)
}
return list
}
func main() {
// create a list from array of integers
intArr := []int{10, 20, 30, 40, 50, 60}
list1 := CreateLinkedList(intArr)
// create a list from array of strings
strArr := []string{"foo", "bar", "baz", "faz"}
list2 := CreateLinkedList(strArr)
// test inserting at the beginning
list2.AddBeforeHead("hello")
fmt.Println(list1.Display())
fmt.Println(list2.Display())
}
Some official references covering basics of Generics can be found here:
https://go.dev/doc/tutorial/generics
https://go.dev/blog/intro-generics
https://go.dev/tour/generics/1
You can do it either by using interfaces and runtime checks (as you've discovered), or by using code generation. These are the current options you have in Go for generic programming. The Go team is working to add generics to the language - it's a work in progress, and everyone is free to participate in the discussion. Once generics exist, they will provide the solution you seek here.
As for interfaces vs. code generation, there are the performance implications you've mentioned. Code generation will generate tighter code that doesn't need to do runtime checks for most operations; on the other hand, it adds a bit of complexity to the build process of your project. These are the usual tradeoffs of having something resolved at run-time vs. precomputing things at compile-time.
er, I am trying to learn go by implementing a random graph. I get an error on n.value undefined (type int has no field or method value), and n.neigbours undefined (type int has no field or method neigbours). I can not understand that compilation error as i create a new slice of nodesnr size of empty nodes in the g.nodes = make([]node, g.nodesnr). What is the problem?
package main
import (
"fmt"
//"math/rand"
)
type node struct {
value int
neigbours []int
}
type edge struct {
source int
sink int
}
type graph struct {
nodesnr, edgesnr int
nodes []node
edges chan edge
}
func main() {
randomGraph()
}
func input(tname string) (number int) {
fmt.Println("input a number of " + tname)
fmt.Scan(&number)
return
}
func randomGraph() (g graph) {
g = graph{nodesnr: input("nodes"), edgesnr: input("edges")}
g.addNodes()
for i := 0; i < g.nodesnr; i++ {
fmt.Println(g.nodes[i].value)
}
//g.addEdges()
return
}
func (g *graph) addNodes() {
g.nodes = make([]node, g.nodesnr)
for n := range g.nodes {
n.value = 2
n.neigbours = nil
return
}
}
func (g *graph) addEdges() {
g.edges = make(chan edge)
for i := 0; i < g.edgesnr; i++ {
//g.newEdge()
return
}
}
/*
func (g* graph) newEdge(){
e := new(edge)
e.source, e.sink = rand.Intn(g.nodesnr), rand.Intn(g.nodesnr)
g.edges <-e*
//g.addEdge()
}
*/
func (g *graph) edgeCheck(ep *edge) string {
if ep.source == ep.sink {
return "self"
}
//if(g.neigbourCheck(g.nodes[ep.source].neigbours, ep.sink) OR g.neigbourCheck(g.nodes[ep.sink].neigbours, ep.source){
// return "present"
return "empty"
}
func (g *graph) neigbourCheck(neigbours []node, node int) bool {
for neigbour := range neigbours {
if node == neigbour {
return true
}
}
return false
}
func (g *graph) addEdge() {
e := <-g.edges
switch etype := g.edgeCheck(&e); etype {
case "present":
fallthrough
case "self":
fmt.Println("self")
//go g.newEdge()
case "empty":
//g.nodes[e.source] = append(g.nodes[e.source], e.sink),
//g.nodes[e.sink] = append(g.nodes[e.sink], e.source)
fmt.Println("empty")
default:
fmt.Println("something went wrong")
}
}
Playground
Your error lies on line 47
for n := range g.nodes
When iterating over a slice, when using only one value, that value (n) will be set to the index, which is of type int. What you need to do is to change the line to:
for _, n := range g.nodes
This means that you discard the index but put the value in n instead.
Edit
n will be a copy of the value which means any changes made to n will not affect the node in the slice. To edit the node in the slice, you should actually get the index instead of the value:
for i := range g.nodes {
g.nodes[i].value = 2
g.nodes[i].neigbours = nil
return
}