问题分析
小S的问题是模拟多米诺骨牌倒下的过程,并确定哪些骨牌最终仍然保持竖立。骨牌的状态由字符串表示:
L:该位置的骨牌将向左倒。R:该位置的骨牌将向右倒。.:该位置的骨牌初始时竖立,可能保持竖立或倒下。
需要解决的问题:
- 确定哪些骨牌因为左右力量平衡而保持竖立。
- 确定哪些骨牌因为两侧无推力而保持竖立。
- 模拟整个倒下过程后统计竖立骨牌的数量和位置。
具体规则:
- 如果骨牌是初始竖立状态(
.),则需检查它的左侧和右侧是否存在推力。 - 若左侧存在推力(
R)且右侧存在推力(L),则检查左右推力距离是否相等。 - 若两侧均无推力,则该骨牌保持竖立。
- 其余情况下,骨牌将被推倒。
代码功能
代码拆解和详细解释
def solution(n, data):
result = []
i = 0
while i < n:
# 如果当前是竖立的骨牌
if data[i] == '.':
# 看前后是否有力量平衡
left = i - 1
right = i + 1
# 检查左边有无推向它的骨牌
while left >= 0 and data[left] == '.':
left -= 1
# 检查右边有无推向它的骨牌
while right < n and data[right] == '.':
right += 1
# 如果左右力量平衡,则该骨牌保持竖立
if (left >= 0 and data[left] == 'R') and (right < n and data[right] == 'L'):
# 只在 R 和 L 之间的竖立骨牌平衡
if right - i == i - left:
result.append(i + 1)
elif (left < 0 or data[left] != 'R') and (right >= n or data[right] != 'L'):
# 左右没有推向它的力量
result.append(i + 1)
i += 1
# 返回结果
if len(result) == 0:
return "0"
else:
return f"{len(result)}:" + ",".join(map(str, result))
# 测试用例
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
核心逻辑:
-
遍历字符串中的每一个骨牌:
- 如果骨牌是
L或R,不需要进一步处理。 - 如果骨牌是
.,需要判断其是否受到左右推力影响。
- 如果骨牌是
-
通过循环检查左侧和右侧的最近非竖立骨牌。
- 左推力来自最近的
R。 - 右推力来自最近的
L。
- 左推力来自最近的
-
判断左右推力是否平衡:
- 若左侧为
R,右侧为L,且两侧距离相等,则该骨牌保持竖立。 - 若左右两侧均无推力,则该骨牌保持竖立。
- 若左侧为
-
将符合条件的骨牌位置记录在结果列表中。
结果构造:
- 若没有骨牌保持竖立,则返回
"0"。 - 若有骨牌保持竖立,则返回竖立骨牌的数量和对应位置,格式为
数量:位置1,位置2,...。
测试用例分析
# 测试用例 1
print(solution(14, ".L.R...LR..L..") == "4:3,6,13,14")
-
初始状态:
.L.R...LR..L.. -
模拟过程:
- 第 3 个骨牌:左侧最近为
L,右侧最近为R,距离相等,因此保持竖立。 - 第 6 个骨牌:两侧无推力,因此保持竖立。
- 第 13、14 个骨牌:两侧无推力,因此保持竖立。
- 第 3 个骨牌:左侧最近为
-
最终结果:4 个骨牌保持竖立,位置为
3, 6, 13, 14。
性能分析
-
时间复杂度:
- 遍历每个骨牌需要
O(n)。 - 对于每个竖立骨牌,向左右查找最近的推力骨牌需要
O(n)(最坏情况)。 - 因此,总时间复杂度为
O(n^2)。
- 遍历每个骨牌需要
-
空间复杂度:
- 使用了一个结果列表存储竖立骨牌的位置,空间复杂度为
O(k),其中k为保持竖立的骨牌数量。
- 使用了一个结果列表存储竖立骨牌的位置,空间复杂度为
对于输入规模适中的问题(如n <= 10^4),该解法是可以接受的。