leetcode-daily/old/golang/2202/220221-CN.go

166 lines
2.8 KiB
Go

package main
import "fmt"
type Node struct {
Pos int
Time int
Next *Node
}
type Queue struct {
front *Node
rear *Node
count uint64
}
func (q *Queue) Initialise() {
q.front = &Node{}
q.rear = q.front
q.count = 0
}
func (q *Queue) Push(node *Node) {
q.rear.Next = node
q.rear = node
q.count++
}
func (q *Queue) Size() uint64 {
return q.count
}
func (q *Queue) Empty() bool {
return q.count == 0
}
func (q *Queue) Pop() {
if q.count <= 0 {
panic("trying to dequeue an empty queue")
}
q.front = q.front.Next
q.count--
}
func (q *Queue) Top() Node {
return *(q.front.Next)
}
func (q *Queue) TopAndPop() (ret Node) {
ret = q.Top()
q.Pop()
return
}
type Queue2 struct {
nodes []Node
}
func (q *Queue2) Initialise() {
q.nodes = make([]Node, 0)
}
func (q *Queue2) Push(node *Node) {
q.nodes = append(q.nodes, *node)
}
func (q *Queue2) Size() int {
return len(q.nodes)
}
func (q *Queue2) Empty() bool {
return len(q.nodes) == 0
}
func (q *Queue2) Pop() {
if len(q.nodes) <= 0 {
panic("trying to dequeue an empty queue")
}
q.nodes = q.nodes[1:]
}
func (q *Queue2) Top() Node {
return q.nodes[0]
}
func (q *Queue2) TopAndPop() (ret Node) {
ret = q.Top()
q.Pop()
return
}
/**
* Warning: This solution did not pass all the test cases (TLE).
* However, an exact re-implementation in C++ does,
* the reason is still unknown.
* The algorithm described should have a time complexity of O(n)
* This golang version passed 41 / 43 test cases, which is
* slightly better than the C# version (39 / 43).
*/
func pushDominoes(dominoes string) (ret string) {
// Queue written by hand.
// Interval: (front, rear]
var q Queue
q.Initialise()
n := len(dominoes)
result := make([]int, n)
lastModified := make([]int, n)
for i, v := range dominoes {
if v != '.' {
q.Push(&Node{
Pos: i,
Time: 1,
})
lastModified[i] = 1
if v == 'L' {
result[i] = -1
} else {
result[i] = 1
}
}
}
for !q.Empty() {
node := q.TopAndPop()
if node.Pos > 0 && (lastModified[node.Pos-1] == node.Time+1 || lastModified[node.Pos-1] == 0) && result[node.Pos] < 0 {
if lastModified[node.Pos-1] == 0 {
q.Push(&Node{
Pos: node.Pos - 1,
Time: node.Time + 1,
})
lastModified[node.Pos-1] = node.Time + 1
}
result[node.Pos-1]--
} else if node.Pos < n-1 && (lastModified[node.Pos+1] == node.Time+1 || lastModified[node.Pos+1] == 0) && result[node.Pos] > 0 {
if lastModified[node.Pos+1] == 0 {
q.Push(&Node{
Pos: node.Pos + 1,
Time: node.Time + 1,
})
lastModified[node.Pos+1] = node.Time + 1
}
result[node.Pos+1]++
}
}
for _, v := range result {
if v < 0 {
ret += "L"
} else if v > 0 {
ret += "R"
} else {
ret += "."
}
}
return
}
func main() {
// fmt.Println(pushDominoes("RR.L"))
fmt.Println(pushDominoes(".L.R...LR..L.."))
}