【蓝桥杯C/C++】翻转游戏:多种实现与解法解析



博客主页:[小ᶻZ࿆] 本文专栏: 蓝桥杯C/C++


文章目录



💯题目

在蓝桥镇,妮妮发明了一个新的游戏------翻转游戏。游戏中有一个开关,可以处于两种状态:开(用 1 表示)和关(用 0 表示)。妮妮发现,无论开关当前处于何种状态,他都可以通过一次操作使得开关的状态翻转。现在,妮妮告诉你开关当前的状态 x,他想知道如果他做一次操作,开关的状态会变成什么。你能帮助他解答这个问题吗?

输入格式:

输入仅一行,包含一个整数 x (0 ≤ x ≤ 1),表示开关当前的状态。

输出格式:

输出一行,表示如果妮妮做一次操作后,开关的状态。

样例输入:

0

样例输出:

1

在这个样例中,开关当前的状态是关(0),所以妮妮做一次操作后,开关的状态会变为开(1)。

运行限制:

语言 最大运行时间 最大运行内存
C++ 1s 128M
C 1s 128M
Java 2s 128M
Python3 3s 128M

💯问题分析

这个问题本质上是一个开关翻转问题,开关的状态只有两种:0 和 1。因此,我们可以很方便地通过数学运算、位运算、逻辑运算等多种方式实现翻转操作。接下来我们将以 C++ 为例,详细讲解每种方法的实现,并分析其思路和适用性。


解法一:减法法

这是最直观的一种解法,即利用数学运算来实现状态翻转。我们知道开关有两种状态:0 和 1。那么无论 x 的初始状态是 0 还是 1,都可以通过 1 - x 的方式得到翻转后的状态。

代码实现:

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
	std::ios::sync_with_stdio(false);
    int x;
    cin >> x;
    cout << 1 - x << endl;
    return 0;
}

思路分析:

对于当前状态 x

  • 如果 x0,那么 1 - x 的结果为 1
  • 如果 x1,那么 1 - x 的结果为 0

通过简单的减法操作,我们可以实现状态的翻转。这种解法简单明了,代码也非常简洁,易于理解。其计算量为常数级别,时间复杂度为 O ( 1 ) O(1) O(1),适合大多数场景使用。


解法二:位运算解法

利用位运算的异或操作(^)实现状态翻转也是一种很高效的方法。在二进制逻辑中,异或操作可以用来做翻转。

  • 0 ^ 1 = 1
  • 1 ^ 1 = 0

也就是说,当前状态与 1 做异或运算,就可以实现翻转操作。

代码实现:

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
	std::ios::sync_with_stdio(false);
    int x;
    cin >> x;
    cout << (x ^ 1) << endl;
    return 0;
}

思路分析:

在 C++ 中,^ 是按位异或运算符。当两个位不同的时候,结果为 1,相同则为 0。因此 x ^ 1 的效果是:

  • x0 时,0 ^ 1 得到 1
  • x1 时,1 ^ 1 得到 0

这种解法的优点在于,它利用了位运算的高效性。位运算的执行速度通常比数学运算更快,因此在需要极高性能的场合,位运算是不错的选择。


解法三:逻辑非解法

我们还可以通过逻辑非运算符 ! 来实现状态翻转。在 C++ 中,逻辑非运算符 ! 可以将布尔值的真假互换。

  • !0 == true,转为整数就是 1
  • !1 == false,转为整数就是 0

代码实现:

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
	std::ios::sync_with_stdio(false);
    int x;
    cin >> x;
    cout << !x << endl;
    return 0;
}

思路分析:

逻辑非运算符可以将 0 变为 1,将 1 变为 0。虽然逻辑非运算符通常用于布尔逻辑判断,但在这种只有 01 两个状态的问题中,也可以巧妙地应用。利用逻辑非运算符的结果自动转换为整数,可以实现状态翻转。


解法四:条件运算符解法

  • 条件运算符(? :)是 C++ 中的一种三目运算符,可以根据条件的真假执行不同的操作。在这个问题中,我们可以根据 x 的值选择输出 10

代码实现:

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
	std::ios::sync_with_stdio(false);
    int x;
    cin >> x;
    cout << (x == 0 ? 1 : 0) << endl;
    return 0;
}

思路分析:

该解法利用了条件运算符的特点:

  • x == 0 时,输出 1
  • x != 0 时,输出 0

这种方法的好处在于可读性很强,逻辑清晰明了,适合用来增强代码的可维护性。


解法五:数组映射法

  • 我们可以定义一个数组,将开关状态映射到它翻转后的状态。利用数组的索引,可以很方便地实现状态翻转。

代码实现:

cpp 复制代码
#include <iostream>
using namespace std;

int main() {
	std::ios::sync_with_stdio(false);
    int x;
    cin >> x;
    int flip[2] = {1, 0}; // 定义翻转表
    cout << flip[x] << endl;
    return 0;
}

思路分析:

在这个解法中,我们定义了一个数组 flip,其中:

  • flip[0]1
  • flip[1]0

输入的状态 x(只能是 01)可以直接作为数组的索引,通过查表的方式得到翻转后的状态。这种解法的优点在于,扩展性较好。如果将来状态种类增多,只需要扩展数组即可,代码的改动最小。


不同解法的比较

  1. 减法法 (1 - x)

    • 优点:简单、直观,易于实现。
    • 缺点:不够灵活,对于状态数较多的场景不适用。
  2. 位运算解法 (x ^ 1)

    • 优点:利用位运算的高效性,性能优异。
    • 缺点:代码可能对某些不熟悉位运算的程序员不够直观。
  3. 逻辑非解法 (!x)

    • 优点:逻辑运算的方式实现状态翻转,简单易懂。
    • 缺点:逻辑非运算符通常用于布尔类型,可能会降低代码的可读性。
  4. 条件运算符解法 (x == 0 ? 1 : 0)

    • 优点:逻辑清晰,代码可读性强。
    • 缺点:代码稍显冗长,相较于其他方法不够简洁。
  5. 数组映射法 (flip[x])

    • 优点:扩展性好,可以方便地增加状态种类。
    • 缺点:对当前只有两种状态的情形而言,显得有些多余。

💯小结


  • 如果代码简洁性和易读性是主要考虑因素,那么减法法 (1 - x) 是最优选择。
  • 如果需要追求极致的性能,或者对位运算熟悉且希望代码执行效率更高,位运算解法 (x ^ 1) 是不错的选择。
  • 如果问题需要在逻辑判断的基础上扩展为多状态翻转,数组映射法可以提高代码的扩展性和可维护性。.


相关推荐
OTWOL43 分钟前
两道数组有关的OJ练习题
c语言·开发语言·数据结构·c++·算法
QQ同步助手1 小时前
C++ 指针进阶:动态内存与复杂应用
开发语言·c++
qq_433554541 小时前
C++ 面向对象编程:递增重载
开发语言·c++·算法
易码智能1 小时前
【EtherCATBasics】- KRTS C++示例精讲(2)
开发语言·c++·kithara·windows 实时套件·krts
一只自律的鸡1 小时前
C语言项目 天天酷跑(上篇)
c语言·开发语言
ཌ斌赋ད1 小时前
FFTW基本概念与安装使用
c++
薄荷故人_2 小时前
从零开始的C++之旅——红黑树封装map_set
c++
悲伤小伞2 小时前
C++_数据结构_详解二叉搜索树
c语言·数据结构·c++·笔记·算法
m0_675988233 小时前
Leetcode3218. 切蛋糕的最小总开销 I
c++·算法·leetcode·职场和发展
佳心饼干-6 小时前
C语言-09内存管理
c语言·算法