166 lines
2.8 KiB
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.."))
|
|
}
|