Algorithm problem push domino simulation, queue and black magic

Posted by DavidT on Fri, 25 Feb 2022 05:43:40 +0100

Push domino simulation, queue and dark magic


Arrange n dominoes in a row and erect each dominoes vertically. At the beginning, push some dominoes to the left or right at the same time.

Every second, the dominoes that fall to the left push the adjacent dominoes to the left. Similarly, a domino upside down to the right will push the adjacent domino standing on its right.

If there are dominoes falling down on both sides of a vertically erected dominoes, the dominoes will remain unchanged due to the balance of forces.

As far as this is concerned, we will think that a falling domino will not exert additional force on other falling or fallen dominoes.

Give you a string dominoes to represent the initial state of this row of dominoes, where:

dominoes[i] = 'L',Represents the second i A domino was pushed to the left,
dominoes[i] = 'R',Represents the second i The dominoes were pushed to the right,
dominoes[i] = '.',It means that the third party has not been promoted i Dominoes.

Returns a string representing the final state.

Source: LeetCode 838 push-dominoes


Input: dominoes = ".L.R...LR..L.."


At first, I wanted to use the simulation method, but the author was too good, and the things I wrote exceeded the time limit 😭, It will be explained in detail later. Analyzing this problem, the difficulty lies in how to deal with the card between the two cards when the card on the left falls to the right and the card on the right falls to the left. This problem can be abstracted as "R" and "L" "The problem of card matching is associated with the problem of expression evaluation and bracket matching discussed in the course of learning stack in the data structure course. However, the above problem is only to solve the arithmetic problem, and the order of elements after operation in and out of the stack is irrelevant at the output level. This problem is essentially a string processing problem, which has requirements for the order of elements, and using the stack will lead to local problems It was troublesome for the Department to reverse, so we decided to use the queue to solve the problem.

The queue algorithm is described as follows:

1) Traverse the dominoes from left to right. If the cards are standing or leaning right, join the team;

2) If the card is left leaning, it will be out of the team. If there are cards in the queue, the right leaning card will also be out of the team;

However, the out of the queue here cannot be a simple in and out. Before leaving the queue, you need to deal with the cards in the queue:

1) If the head of the team is an upright card, all the left leaning cards will fall to the left when they come in, and the right leaning cards will directly go out of the team;

2) If the head of the team is a right leaning card, the right leaning card will first reverse the queue to the right, and the left leaning card will reverse.

How to deal with inversion is also a thorny problem. Here, the double pointer method is used:

1) Set a pointer at the head and tail of the team respectively;

2) The two pointers are facing each other. The first pointer points to the right and the tail pointer to the left

3) Stop when two pointers meet.


So how to implement the queue? The string of python is an immutable variable and cannot be modified directly. It needs to be converted into a list. The list is easy to modify, but it is difficult to control its in and out when there is a queue. Therefore, the author uses the method of "pseudo queue" and the idea of queue, but in essence, it uses the double pointer method of two pointers at the beginning and end of the team. The data structure is as follows:

queue = [0,0,'']

The first two elements are the head and tail pointers respectively, and the last one represents the status of the queue. Review your ideas and what specific actions to take when leaving the team. You need to consider the elements when you first joined the team. "L" will only trigger out of the queue, so the queue status has "" empty queue, "" Upright card queue, "R" right leaning queue has three states.

It should be noted that when there is no "L" or "R" at the end of the original string, the queue cannot be triggered. Especially in the case of "R" queue, all cards fall to the right, and the queue needs to be emptied after traversal:

class Solution:
 def pushDominoes(self, dominoes: str) -> str:
  queue = [0,0,''] # Initialize queue
  dominoes = list(dominoes) # Tabulation is convenient for modification
  for i in range(len(dominoes)):
   if queue[-1] == '':
    if dominoes[i] == '.':
     queue = [i,i,'.']
    elif dominoes[i] == 'R':
     queue = [i,i,'R']
   elif queue[-1] == '.':
    if dominoes[i] == '.':
     queue[1] = i
    elif dominoes[i] == 'R':
     queue = [i,i,'R']
    elif dominoes[i] == 'L':
     queue[-1] = ''
     for j in range(queue[0],queue[1]+1):
      dominoes[j] = 'L'
   elif queue[-1] == 'R':
    if dominoes[i] == 'R':
     for j in range(queue[0], i):
      dominoes[j] = 'R'
     queue = [i,i,'R']
    elif dominoes[i] == '.':
     queue[1] = i
    elif dominoes[i] == 'L':
     queue[-1] = ''
     rcur, lcur = queue[0], i
     while rcur<lcur:
      dominoes[rcur], dominoes[lcur] = 'R', 'L'
      rcur+=1; lcur-=1
  if queue[-1] == 'R': # Make sure all elements are out of the team
   queue[-1] = ''
   for i in range(queue[0],len(dominoes)):
    dominoes[i] = 'R'
  return ''.join(dominoes)

A failed simulation

Too many loops, timeout, written as 💩 When the mountain was over and there was no rescue, Bo Jun smiled:

class Solution:
 def pushDominoes(self, dominoes: str) -> str:
    dominoes = list(dominoes)
    rcur, lcur = -1, -1
    rl_set = []
    no_dot = []
    for i in range(len(dominoes)):
      if dominoes[i] == 'R' :
        rcur = i
      elif dominoes[i] == 'L' and rcur != -1:
        lcur = i
        rcur, lcur = -1, -1
      i += 1
    for rl in rl_set:
      rcur, lcur = rl
      no_dot.extend([i for i in range(rcur, lcur+1)])
      while rcur<lcur:
        dominoes[rcur] = 'R'
        dominoes[lcur] = 'L'
    p = 0
    for i in range(len(dominoes)): 
      if i in no_dot:
        p = 0
      if dominoes[i] == 'L':
        p = 0
        for j in range(i-1,-1,-1):
          if dominoes[j] == '.':
            dominoes[j] = 'L'
      elif dominoes[i] == 'R':
        p = 1
      elif p == 1 and dominoes[i] == '.' :
        dominoes[i] = 'R'
    return ''.join(dominoes)

Black magic

All string processing problems are inseparable from black magic, outrageous, author: [sun's cat]:

class Solution:
 def pushDominoes(self, dominoes: str) -> str:
  od = ""
  while dominoes != od:
   od = dominoes
   dominoes = dominoes.replace("R.L", "T")
   dominoes = dominoes.replace(".L", "LL")
   dominoes = dominoes.replace("R.", "RR")
   dominoes = dominoes.replace("T", "R.L")
  return dominoes

Topics: Python Algorithm data structure leetcode queue