Skip to content

Commit f1e5aa7

Browse files
committed
problem 24, 26
1 parent df03cc9 commit f1e5aa7

File tree

7 files changed

+185
-0
lines changed

7 files changed

+185
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ Number | Difficulty | Asked By
4040
[#21](problem021) | EASY | Snapchat
4141
[#22](problem022) | MEDIUM | Microsoft
4242
[#23](problem023) | EASY | Google
43+
[#24](problem024) | EASY | Google

problem024/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
## Daily Coding Problem: Problem #24 [Medium]
2+
Good morning! Here's your coding interview problem for today.
3+
4+
This problem was asked by Google.
5+
6+
Implement locking in a binary tree. A binary tree node can be locked or unlocked only if all of its descendants or ancestors are not locked.
7+
8+
Design a binary tree node class with the following methods:
9+
10+
---
11+
* `is_locked`, which returns whether the node is locked
12+
* `lock`, which attempts to lock the node. If it cannot be locked, then it should return false. Otherwise, it should lock it and return true.
13+
* `unlock`, which unlocks the node. If it cannot be unlocked, then it should return false. Otherwise, it should unlock it and return true.
14+
---
15+
16+
You may augment the node to add parent pointers or any other property you would like. You may assume the class is used in a single-threaded program, so there is no need for actual locks or mutexes. Each method should run in O(h), where h is the height of the tree.

problem024/problem024.go

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package problem024
2+
3+
type binaryTree struct {
4+
lockedDescendantsCount int
5+
locked bool
6+
parent *binaryTree
7+
left *binaryTree
8+
right *binaryTree
9+
}
10+
11+
func NewBinaryTree(left *binaryTree, right *binaryTree) *binaryTree {
12+
node := binaryTree{
13+
parent: nil,
14+
lockedDescendantsCount: 0,
15+
locked: false,
16+
left: left,
17+
right: right,
18+
}
19+
if right != nil {
20+
right.parent = &node
21+
}
22+
if left != nil {
23+
left.parent = &node
24+
}
25+
return &node
26+
}
27+
28+
func (node *binaryTree) IsLocked() bool {
29+
return node.locked
30+
}
31+
32+
func (node *binaryTree) Lock() bool {
33+
if node.lockedDescendantsCount > 0 {
34+
return false
35+
}
36+
ascendants := make([]*binaryTree, 0, 64)
37+
for cursor := node.parent; cursor != nil; cursor = cursor.parent {
38+
if cursor.locked {
39+
return false
40+
}
41+
ascendants = append(ascendants, cursor)
42+
}
43+
for _, ascendant := range ascendants {
44+
ascendant.lockedDescendantsCount++
45+
}
46+
node.locked = true
47+
return true
48+
}
49+
50+
func (node *binaryTree) Unlock() bool {
51+
if node.lockedDescendantsCount > 0 {
52+
return false
53+
}
54+
ascendants := make([]*binaryTree, 0, 64)
55+
for cursor := node.parent; cursor != nil; cursor = cursor.parent {
56+
if cursor.locked {
57+
return false
58+
}
59+
ascendants = append(ascendants, cursor)
60+
}
61+
for _, ascendant := range ascendants {
62+
ascendant.lockedDescendantsCount--
63+
}
64+
node.locked = false
65+
return true
66+
}

problem024/problem024_test.go

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package problem024
2+
3+
import (
4+
"os"
5+
"testing"
6+
)
7+
8+
var tree *binaryTree
9+
10+
func TestMain(m *testing.M) {
11+
tree = NewBinaryTree(
12+
NewBinaryTree(nil, nil),
13+
NewBinaryTree(
14+
NewBinaryTree(nil, nil),
15+
NewBinaryTree(nil, nil),
16+
),
17+
)
18+
os.Exit(m.Run())
19+
}
20+
21+
func TestBinaryTree_Lock(t *testing.T) {
22+
if tree.right.IsLocked() {
23+
t.Log("right node already locked")
24+
t.FailNow()
25+
}
26+
if !tree.right.Lock() || !tree.right.IsLocked() || tree.lockedDescendantsCount != 1 {
27+
t.Log("failed to lock right node")
28+
t.FailNow()
29+
}
30+
if tree.Lock() || tree.right.right.Lock() {
31+
t.Log("invalid lock")
32+
t.FailNow()
33+
}
34+
}
35+
36+
func TestBinaryTree_Unlock(t *testing.T) {
37+
if tree.Unlock() || tree.right.right.Unlock() {
38+
t.Log("invalid lock")
39+
t.FailNow()
40+
}
41+
if !tree.right.Unlock() {
42+
t.Log("failed to unlock right node")
43+
t.FailNow()
44+
}
45+
}

problem026/README.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Daily Coding Problem: Problem #26 [Medium]
2+
3+
Good morning! Here's your coding interview problem for today.
4+
5+
This problem was asked by Google.
6+
7+
Given a singly linked list and an integer `k`, remove the `k`th last element from the list. `k` is guaranteed to be smaller than the length of the list.
8+
9+
The list is very long, so making more than one pass is prohibitively expensive.
10+
11+
Do this in constant space and in one pass.
12+
13+

problem026/problem026.go

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package problem026
2+
3+
type linkedList struct {
4+
value int
5+
next *linkedList
6+
}
7+
8+
func (node *linkedList) FromLast(reverseIndex int) *linkedList {
9+
formerCursor, latterCursor := node, node
10+
for i := 0; i < reverseIndex; i++ {
11+
latterCursor = latterCursor.next
12+
}
13+
for latterCursor.next != nil {
14+
formerCursor, latterCursor = formerCursor.next, latterCursor.next
15+
}
16+
return formerCursor
17+
}

problem026/problem026_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package problem026
2+
3+
import "testing"
4+
5+
func TestLinkedList_FromLast(t *testing.T) {
6+
node := &linkedList{
7+
value: 3,
8+
next: &linkedList{
9+
value: 2,
10+
next: &linkedList{
11+
value: 1,
12+
next: &linkedList{
13+
value: 0,
14+
next: nil,
15+
},
16+
},
17+
},
18+
}
19+
if node.FromLast(0).value != 0 {
20+
t.Log(node.FromLast(0))
21+
t.FailNow()
22+
}
23+
if node.FromLast(2).value != 2 {
24+
t.Log(node.FromLast(2))
25+
t.FailNow()
26+
}
27+
}

0 commit comments

Comments
 (0)