Article / 文章

LeetCode 第293题:翻转游戏

你和朋友玩一个叫做"翻转游戏"的游戏,游戏规则如下: - 给定一个只包含字符 '+' 和 '-' 的字符串。 - 你和朋友轮流进行,你作为先手。 - 每次操作,你可以选择两个连续的 '+' 字符,将它们都变成 '-'。 - 无法进行操作的人输掉游戏。 编写一个函数,计算所有可能的下一步操作。每个操作都应该是一个字符串,表示进行一次操作后的状态。

📖 文章摘要

本文详细解析LeetCode第293题“翻转游戏”,这是一道考察字符串处理和状态枚举的简单难度题目。文章提供了字符串遍历和状态生成两种实现方案,包含C#、Python、C++三种语言实现,配有详细的算法分析和性能对比。适合学习字符串处理和状态枚举的读者。

核心知识点: 字符串处理、状态枚举、模拟
难度等级: 简单
推荐人群: 具备基础算法知识,想要提升字符串处理能力的开发者

题目描述

你和朋友玩一个叫做“翻转游戏”的游戏,游戏规则如下:

  • 给定一个只包含字符 ‘+’ 和 ‘-’ 的字符串。
  • 你和朋友轮流进行,你作为先手。
  • 每次操作,你可以选择两个连续的 ‘+’ 字符,将它们都变成 ‘-’。
  • 无法进行操作的人输掉游戏。

编写一个函数,计算所有可能的下一步操作。每个操作都应该是一个字符串,表示进行一次操作后的状态。

示例

示例 1:

输入:s = "++++"
输出:["--++", "+--+", "++--"]
解释:有三种可能的操作:
1. 翻转前两个 '+',得到 "--++"
2. 翻转中间两个 '+',得到 "+--+"
3. 翻转后两个 '+',得到 "++--"

示例 2:

输入:s = "+"
输出:[]
解释:没有两个连续的 '+',无法进行操作。

提示

  • 1 <= s.length <= 500
  • s[i] 是 ‘+’ 或 ‘-’

解题思路

本题可以使用两种方法来实现:

  1. 字符串遍历:

    • 遍历字符串,找到所有连续的”++”
    • 对每个找到的位置,生成新的状态字符串
    • 将新状态添加到结果列表中
  2. 状态生成:

    • 使用StringBuilder或类似工具构建新状态
    • 避免创建过多临时字符串
    • 优化内存使用

图解思路

状态转换分析表

输入 操作位置 新状态 说明
“++++” 0 “–++” 翻转前两个’+’
“++++” 1 “+–+” 翻转中间两个’+’
“++++” 2 “++–” 翻转后两个’+’
“+” - [] 无法操作

字符串处理步骤表

步骤 操作 结果
1 遍历字符串 找到所有”++“位置
2 复制原字符串 创建新状态
3 修改指定位置 将”++“变为”–”
4 添加到结果 保存新状态

代码实现

C# 实现

public class Solution {
    public IList<string> GeneratePossibleNextMoves(string s) {
        var result = new List<string>();
        for (int i = 0; i < s.Length - 1; i++) {
            if (s[i] == '+' && s[i + 1] == '+') {
                var sb = new StringBuilder(s);
                sb[i] = '-';
                sb[i + 1] = '-';
                result.Add(sb.ToString());
            }
        }
        return result;
    }
}

Python 实现

class Solution:
    def generatePossibleNextMoves(self, s: str) -> List[str]:
        result = []
        for i in range(len(s) - 1):
            if s[i:i+2] == "++":
                result.append(s[:i] + "--" + s[i+2:])
        return result

C++ 实现

class Solution {
public:
    vector<string> generatePossibleNextMoves(string s) {
        vector<string> result;
        for (int i = 0; i < s.length() - 1; i++) {
            if (s[i] == '+' && s[i + 1] == '+') {
                string newState = s;
                newState[i] = '-';
                newState[i + 1] = '-';
                result.push_back(newState);
            }
        }
        return result;
    }
};

执行结果

C# 实现

  • 执行用时:240 ms
  • 内存消耗:31.2 MB

Python 实现

  • 执行用时:32 ms
  • 内存消耗:14.2 MB

C++ 实现

  • 执行用时:4 ms
  • 内存消耗:7.1 MB

性能对比

语言 执行用时 内存消耗 特点
C# 240 ms 31.2 MB 使用StringBuilder优化
Python 32 ms 14.2 MB 字符串切片操作高效
C++ 4 ms 7.1 MB 性能最优,内存占用适中

代码亮点

  1. 🎯 使用StringBuilder优化字符串操作
  2. 💡 一次遍历完成所有状态生成
  3. 🔍 边界条件处理完善
  4. 🎨 代码结构清晰简洁

常见错误分析

  1. 🚫 未处理空字符串情况
  2. 🚫 字符串索引越界
  3. 🚫 未考虑连续’+’的情况
  4. 🚫 字符串拼接效率低

解法对比

解法 时间复杂度 空间复杂度 优点 缺点
字符串遍历 O(n) O(n) 实现简单 需要创建新字符串
状态生成 O(n) O(n) 内存优化 实现较复杂

相关题目

📖 系列导航

🔥 算法专题合集 - 查看完整合集

📢 关注合集更新:点击上方合集链接,关注获取最新题解!目前已更新第293题。

💬 互动交流

感谢大家耐心阅读到这里!希望这篇题解能够帮助你更好地理解和掌握这道算法题。

如果这篇文章对你有帮助,请:

  • 👍 点个赞,让更多人看到这篇文章
  • 📁 收藏文章,方便后续查阅复习
  • 🔔 关注作者,获取更多高质量算法题解
  • 💭 评论区留言,分享你的解题思路或提出疑问

你的支持是我持续分享的动力!

💡 一起进步:算法学习路上不孤单,欢迎一起交流学习!