AI刷题72题 | 豆包Marscode AI刷题

108 阅读3分钟

问题描述

小 A 将 n 个多米诺骨牌放在一条线上,每一块都垂直竖立。他同时将一些骨牌向左或向右推倒。注意:不会出现连续向左或者向右推的情况。 每过一秒,被推向左边或右边的骨牌会将左边或右边的相邻骨牌推倒。当一个骨牌,其左边倒向它的骨牌数目与其右边倒向它的骨牌数目相等时,由于力的平衡,该骨牌将依然保持竖立。给定小 A 最初推骨牌的方向,求出最后依然保持竖立的骨牌数目和位置。

问题分析

给定一组多米诺骨牌,初始时有些骨牌被推向左('L')或右('R'),而其他骨牌处于竖立状态('.')。目标是模拟多米诺骨牌倒下的过程,最终返回所有仍然竖立的骨牌的位置。需要考虑到多米诺骨牌的传递效应:当一个骨牌被推倒时,它会推倒相邻的骨牌,直到没有更多骨牌会被推倒为止。

可以通过以下几个步骤来解决这个问题:

  1. 初始化和变量定义

    • 使用一个变量 right 来记录最近的 R 的位置,它表示推向右的骨牌的起始点。
    • 使用 dominoes 字符串来表示多米诺骨牌的状态,R 表示右推,L 表示左推,. 表示竖立状态。
    • standing 用于记录最终竖立的骨牌位置。
  2. 遍历字符串处理推倒的骨牌:(重点:跟踪当前位置骨牌的状态)

    • 如果遇到 R(向右推的骨牌),就更新 right 为当前位置。
    • 如果遇到 L(向左推的骨牌),就检查之前是否有 R 出现过(即是否有骨牌正在向右推倒)。
      • 如果有 R,则从 RL 之间的所有竖立骨牌会平衡地倒下(即左边逐渐倒向 R,右边逐渐倒向 L)。中间的骨牌会左右倒向,相等时保持竖立。
      • 如果没有 R,则只能让所有竖立的骨牌向左倒(即从当前位置向左推)。
  3. 处理最后一段 R... 的情况

    • 如果最后还有 R(即没有 L 在其后),那么所有 R 后面的竖立骨牌都会被推倒。
  4. 统计最终竖立的骨牌

    • 在整个过程结束后,遍历 dominoes 字符串,找出仍然竖立的骨牌(即状态为 . 的骨牌),记录它们的位置。

代码:

std::string solution(int n, std::string dominoes) {
    std::vector<int> standing;

    int right = -1; // 记录最后一次出现的 R 的位置
    
    for (int i = 0; i < n; ++i) {
        if (dominoes[i] == 'R') {
            right = i; // 记录向右推的位置
        } else if (dominoes[i] == 'L') {
            if (right != -1) {
                // 处理 R...L 之间的骨牌
                int start = right + 1;
                int end = i - 1;
                while (start < end) {
                    dominoes[start++] = 'R';
                    dominoes[end--] = 'L';
                }
                right = -1; // 处理完后清除 R 的状态
            } else {
                // 没有 R,只能从当前位置左推到最远
                for (int j = i - 1; j >= 0 && dominoes[j] == '.'; --j) {
                    dominoes[j] = 'L';
                }
            }
        }
    }
    
    // 处理最后一段 R... 的情况,这些骨牌都会被推倒
    if (right != -1) {
        for (int i = right + 1; i < n && dominoes[i] == '.'; ++i) {
            dominoes[i] = 'R';
        }
    }

    // 再次遍历,统计竖立的骨牌
    for (int i = 0; i < n; ++i) {
        if (dominoes[i] == '.') {
            standing.push_back(i + 1);  // 记录竖立的骨牌位置
        }
    }

    // 返回结果
    if (standing.empty()) {
        return "0";
    } else {
        std::string result = std::to_string(standing.size()) + ":";
        for (int i = 0; i < standing.size(); ++i) {
            result += std::to_string(standing[i]);
            if (i != standing.size() - 1) {
                result += ",";
            }
        }
        return result;
    }
}

总结

这道题的重点是关注跟踪当前位置骨牌的状态,通过一次遍历所有动作处理多米诺骨牌的倒下过程,一次遍历中就考虑完了所有的平衡条件。