Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions linked-list-cycle/bus710.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package hello

import "testing"

type ListNode struct {
Val int
Next *ListNode
}

// // Version 1
// func hasCycle(head *ListNode) bool {
// if head == nil {
// return false
// }
// return call(head, make(map[*ListNode]int, 0))
// }
//
// func call(h *ListNode, m map[*ListNode]int) bool {
// if h.Next == nil {
// return false
// }
// if _, ok := m[h]; ok {
// return true
// }
// m[h] = 1
// return call(h.Next, m)
// }

// Version 2
func hasCycle(head *ListNode) bool {
if head == nil {
return false
}
m := map[*ListNode]int{}
for head.Next != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for 문의 조건에 head.Next != nil 가 아닌 head != nil 로 하면, 31 번째 줄의 if 문이 필요없게 되어서 코드가 조금 더 깔끔해지지 않을까 생각이 들었습니다. 어떻게 생각하시나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

첫번째 조건은 사실 제출하면서 추가 된 에러를 핸들링하느라 붙였더니 그렇게 통합 될 수도 있을 것 같네요.

if _, ok := m[head]; !ok {
m[head] = 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 선언해두신 m 은 key 의 존재 여부만 확인하면 되기 때문에 value 의 역할은 사실상 큰 의미가 없어 보입니다. 저는 go 언어를 잘알지는 못하지만, int 대신 struct{} 를 사용하면 별도의 메모리 공간 할당이 필요없다고 하더라구요. 즉, m := map[*ListNode]struct{}{}m 의 타입을 변경할 수도 있을 것 같습니다. 물론, 그럼에도 메모리상 큰 차이는 없을 것 같습니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 저도 들어본 것 같은 얘기네요. 아마도 포인터로 다루기 때문에 구조체를 값으로 쓰면 공간이 덜 든다고 했던 것 같기도...

} else {
return true
}
head = head.Next
}
return false
}

func Test_hasCycle(t *testing.T) {
// Case 0 list
c0_3 := &ListNode{Val: -4}
c0_2 := &ListNode{Val: 0, Next: c0_3}
c0_1 := &ListNode{Val: 2, Next: c0_2}
c0_0 := &ListNode{Val: 3, Next: c0_1}
c0_3.Next = c0_1

// Case 1 list
c1_1 := &ListNode{Val: 2}
c1_0 := &ListNode{Val: 1, Next: c1_1}
c1_1.Next = c1_0

// Case 2 list
c2_0 := &ListNode{Val: 1}

type args struct {
head *ListNode
}
tests := []struct {
name string
args args
want bool
}{
{
name: "case 0",
args: args{head: c0_0},
want: true,
},
{
name: "case 1",
args: args{head: c1_0},
want: true,
},
{
name: "case 2",
args: args{head: c2_0},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := hasCycle(tt.args.head)
if got != tt.want {
t.Errorf("hasCycle() = %v, want %v", got, tt.want)
}
})
}
}