多米诺骨牌均衡状态 | 豆包MarsCode AI刷题
摘要
本文解决了多米诺骨牌均衡状态的问题,给定一个多米诺骨牌的初始状态,模拟骨牌倒下的过程,确定哪些骨牌保持竖立。通过两个辅助数组记录左右推倒骨牌的受力时间,并结合该信息最终输出竖立骨牌的位置。我们提供了详细的解题思路与代码实现。
问题描述
小S玩起了多米诺骨牌,他排列了一行骨牌,并可能将某些骨牌向左或向右推倒。随着骨牌的连锁反应,一些骨牌可能因左右两侧受力平衡而保持竖立。小S想要知道在所有动作完成后,哪些骨牌仍然保持竖立。
给定一个表示骨牌初始状态的字符串,其中:
- "L" 表示该位置的骨牌将向左倒。
- "R" 表示该位置的骨牌将向右倒。
- "." 表示该位置的骨牌初始时保持竖立。
模拟整个骨牌倒下的过程,求出最终保持竖立的骨牌的数量和位置。
示例
-
输入:
输出:'4:3,6,13,14' -
输入:
输出:'0' -
输入:
输出:'1:1'
解题步骤
1. 初始化状态
使用一个数组 finalState 来记录每个骨牌的最终状态:
0表示骨牌保持竖立。- 正整数表示骨牌被向右推倒。
- 负整数表示骨牌被向左推倒。
此外,使用两个辅助数组 timeR 和 timeL 分别记录每个骨牌被右推('R')和左推('L')时的影响时间。这两个数组有助于确定哪些骨牌处于平衡状态。
2. 处理右倒('R')的骨牌
从左到右遍历字符串,遇到 'R' 时:
- 标记当前骨牌为受力状态。
- 从当前骨牌的右侧开始,标记所有竖立的骨牌为向右倒,并记录右推的受力时间。
3. 处理左倒('L')的骨牌
从右到左遍历字符串,遇到 'L' 时:
- 标记当前骨牌为受力状态。
- 从当前骨牌的左侧开始,标记所有竖立的骨牌为向左倒,并记录左推的受力时间。
4. 确定竖立的骨牌
最终,遍历所有骨牌的位置,检查哪些位置的骨牌受力平衡(即 finalState[i] == 0),并且其左右倒力的受力时间一致(timeR[i] == timeL[i])。这些骨牌即为竖立的骨牌。
5. 输出结果
如果有竖立的骨牌,返回这些骨牌的位置(1-based index),并按从大到小的顺序输出。如果没有竖立的骨牌,返回 "0"。
代码实现
Go语言代码
package main
import (
"fmt"
"strconv"
"strings"
)
func solution(num int, data string) string {
// finalState 数组记录每个骨牌的最终状态,0 代表竖立,负数代表向左倒,正数代表向右倒
finalState := make([]int, num)
// 先处理右倒(R)
timeR:=make([]int,num)//记录向右倒时的受力时间
for i := 0; i < num; i++ {
if data[i] == 'R' {
finalState[i] = 2 //初始骨牌不纳入计算
// 向右倒的骨牌会影响之后的骨牌
cnt:=1
for j := i + 1; j < num && data[j] == '.'; j++ {
finalState[j] = 1
timeR[j]=cnt
cnt++
}
}
}
// 然后处理左倒(L)
timeL:=make([]int,num)//记录向左倒时的受力时间
for i := num - 1; i >= 0; i-- {
if data[i] == 'L' {
finalState[i] = 2 //
// 向左倒的骨牌会影响之前的骨牌
cnt:=1
for j := i - 1; j >= 0 && data[j] == '.'; j-- {
finalState[j]--
timeL[j]=cnt
cnt++
}
}
}
// 找出竖立的骨牌,并存入结果
var result []int
for i := 0; i < num; i++ {
if finalState[i] == 0&&timeL[i]==timeR[i] {
result = append(result, i+1) // 1-based index
}
}
// 如果没有竖立的骨牌
if len(result) == 0 {
return "0"
}
// 格式化输出
var builder strings.Builder
builder.WriteString(strconv.Itoa(len(result)))
builder.WriteString(":")
for i := 0; i < len(result)-1; i++ {
builder.WriteString(strconv.Itoa(result[i]))
builder.WriteString(",")
}
builder.WriteString(strconv.Itoa(result[len(result)-1]))
return builder.String()
}
func main() {
// 你可以添加更多的测试用例
fmt.Println(solution(14, ".L.R...LR..L..") == "4:3,6,13,14")
fmt.Println(solution(5, "R....") == "0")
fmt.Println(solution(1, ".") == "1:1")
}
Python代码
def solution(num, data):
"""
该函数接受一个整数 num 和一个字符串 data,表示骨牌的数量和初始状态。
返回保持竖立状态的骨牌位置列表(1-based index),格式为 "<数量>:<位置1>,<位置2>,...<位置N>"。
如果没有骨牌保持竖立,返回 "0"。
"""
# 初始化 finalState 数组,0 表示竖立,-1 表示向左倒,1 表示向右倒
final_state = [0] * num
# 初始化时间数组,用于记录向左倒和向右倒的受力时间
time_r = [0] * num # 向右倒的时间记录
time_l = [0] * num # 向左倒的时间记录
# 处理右倒('R')的影响
for i in range(num):
if data[i] == 'R':
final_state[i] = 2 # 表示该位置是初始向右倒的骨牌
cnt = 1 # 初始化受力时间
for j in range(i + 1, num):
if data[j] == '.':
final_state[j] = 1 # 向右倒的影响
time_r[j] = cnt # 记录向右倒的受力时间
cnt += 1
else:
break # 遇到其他骨牌终止影响
# 处理左倒('L')的影响
for i in range(num - 1, -1, -1):
if data[i] == 'L':
final_state[i] = 2 # 表示该位置是初始向左倒的骨牌
cnt = 1 # 初始化受力时间
for j in range(i - 1, -1, -1):
if data[j] == '.':
final_state[j] -= 1 # 向左倒的影响
time_l[j] = cnt # 记录向左倒的受力时间
cnt += 1
else:
break # 遇到其他骨牌终止影响
# 找出保持竖立的骨牌
result = []
for i in range(num):
if final_state[i] == 0 and time_l[i] == time_r[i]: # 确保向左和向右的受力时间相等
result.append(i + 1) # 1-based index
# 如果没有竖立的骨牌,返回 "0"
if len(result) == 0:
return "0"
# 格式化输出
result_str = f"{len(result)}:" + ",".join(map(str, result))
return result_str
if __name__ == "__main__":
# 测试用例
print(solution(14, ".L.R...LR..L..")
== "4:3,6,13,14") # 应输出 True
print(solution(5, "R....") == "0") # 应输出 True
print(solution(1, ".") == "1:1") # 应输出 True