当前位置: 面试刷题>> 翻转游戏 (经典算法题500道)


翻转游戏题目描述

题目:翻转游戏

给定一个由 '0' 和 '1' 组成的字符串 s,长度为 n。你可以进行如下操作:

  • 选择字符串中的任意两个相邻的字符进行翻转(即 '0' 变成 '1','1' 变成 '0')。
  • 目标是通过有限次翻转操作,使得字符串 s 中所有字符均为 '0'。

请问是否存在一种翻转方式可以达到目标?如果存在,请输出任意一种翻转序列;如果不存在,则输出 "impossible"。

注意

  1. 翻转操作可以多次进行,但每次只能翻转相邻的两个字符。
  2. 翻转序列不需要是最短的,只需证明存在性即可。

示例

输入:s = "0101" 输出:"0000"(或任何可以翻转成 "0000" 的序列,例如 "flip 1", "flip 3")

输入:s = "1110" 输出:"impossible"

解题思路

观察题目可以发现,除了最左边的 '1' 需要通过右侧相邻的 '0' 翻转过来之外,其余的 '1' 都可以通过与其相邻的 '0' 翻转来消除。而最左侧的 '1' 如果没有右侧的 '0' 来翻转,则无法通过有限次操作将其翻转为 '0'。

因此,我们可以得出结论:如果字符串 s 中包含 '1' 的数量是奇数,且最左侧的字符是 '1',则无法通过翻转操作使所有字符都为 '0';否则,存在一种翻转方式。

示例代码

PHP

function canFlipToZero(string $s): string {
    $countOnes = substr_count($s, '1');
    
    // 如果'1'的数量是奇数且第一个字符是'1',则无法翻转成'000...'
    if ($countOnes % 2 != 0 && $s[0] == '1') {
        return "impossible";
    }
    
    // 示例输出,实际不需要翻转序列,因为已经证明了存在性
    return str_repeat('0', strlen($s));
}

// 测试
echo canFlipToZero("0101"); // 输出 "0000"
echo PHP_EOL;
echo canFlipToZero("1110"); // 输出 "impossible"

Python

def can_flip_to_zero(s: str) -> str:
    count_ones = s.count('1')
    
    # 如果'1'的数量是奇数且第一个字符是'1',则无法翻转成'000...'
    if count_ones % 2 != 0 and s[0] == '1':
        return "impossible"
    
    # 示例输出
    return '0' * len(s)

# 测试
print(can_flip_to_zero("0101"))  # 输出 "0000"
print(can_flip_to_zero("1110"))  # 输出 "impossible"

JavaScript

function canFlipToZero(s) {
    let countOnes = 0;
    for (let i = 0; i < s.length; i++) {
        if (s[i] === '1') {
            countOnes++;
        }
        // 如果'1'的数量是奇数且遇到第一个'1',直接返回"impossible"
        if (countOnes % 2 !== 0 && i === 0) {
            return "impossible";
        }
    }
    
    // 示例输出
    return '0'.repeat(s.length);
}

// 测试
console.log(canFlipToZero("0101")); // 输出 "0000"
console.log(canFlipToZero("1110")); // 输出 "impossible"

码小课网站中有更多相关内容分享给大家学习,包括但不限于算法设计、数据结构、编程技巧等,欢迎访问码小课获取更多知识。

推荐面试题