通过将两个连续的 1 转换为 0 来确定游戏获胜者(C++)

2024 年 08 月 29 日 | 阅读 9 分钟

问题介绍

该问题描述围绕着一个非常简单的使用比特的序列游戏,玩家可以轮流改变他们的走法。游戏的目标是将两个连续的1转换为零,这将由提供的走法强化。之后,做出成功走法组合的玩家将有机会获胜。玩家 whose pioneer will be able to substitute all pairs of consecutive 1s by 0s will come out winner. (能够用0替换所有连续1对的先驱者将成为赢家。)

问题概述

初始状态:游戏源于一系列二进制数字(0和1),表示初始位置。

玩家走法:玩家轮流进行走法。一次走法意味着寻找成对出现的1,然后将其变为0。

获胜条件:游戏结束,玩家赢得奖金,当不再发现连续的1时。如果所有成对的1都被转换为0,则归赢家玩家1所有。如果二进制数字在之后仍然有一些1,那么最后剩下的人就是赢家。

C++ 中的实现

在C++语言中,可以利用字符串操作的机制来实现更简单的实现。我们使用名为'determineWinner()'的函数作为输入,它会循环处理成对的0,直到将它们转换为1。之后,我们检查生成的序列,看看谁赢了。

程序

输出

Enter the sequence of 0s and 1s: 110101000110
Iteration 1:
Found pair of consecutive 1s at index 0 and 1. Converting them to 0s.
Found pair of consecutive 1s at index 9 and 10. Converting them to 0s.
Updated sequence: 000101000000
Iteration 2:
Updated sequence: 000101000000
Player 2 wins!

说明

  • 包含头文件

代码包含了执行方向(使用iostream)和字符串操作函数(string)。

  • 函数 determineWinner()

计算机通过接受初始的0和1来评估输出,从而确定游戏的获胜结果。它会遍历序列中的每个元素,比较连续的1对。如果是,它会将它们变为零。这个过程会一直进行,直到序列中不再存在连续的1对。最后,根据 剩余盲点的元素来决定获胜者。

  • 主函数

main() 函数负责引导用户输入二进制数的初始序列。当提供以下初始序列时,将调用 determineWinner() 函数。在游戏结束后(即谁获胜),会显示结果。

  • 详细注释

代码中的注释对流程的每个步骤进行了说明,例如初始化变量、遍历序列以及检查连续的1对以成功完成任务。讨论还提供了关于迭代计数以及函数/序列在每次迭代中如何变化的背景信息。

  • 输出

determineWinner() 函数执行过程中,会顺序向控制台打印一系列不同的消息,以显示游戏的进展情况。这些消息包括:当前版本、每次迭代中发现的1序列的位置索引,以及迭代后的序列变化。

该代码基本上通过让计算机将成对的连续1替换为单个0,为玩家提供了一种更结构化的获胜技术。它包含反馈和详细的数据结果,以帮助用户调试和熟悉语法。

复杂度分析

时间复杂度

代码的时间复杂度主要取决于输入序列的长度。

遍历序列

该算法会反复测试输入序列,直到不再找到由连续两个1组成的组合。在不利情况下,当输入序列只包含1时,代码将迭代多次。对于序列的每次迭代,其渐近增长为O(n),其中n是序列的长度。

查找连续的1对

在执行过程中,代码会遍历序列以在每次迭代中查找连续的1对。该算法的内部循环复杂度O(n),其中n是序列长度。

最终,代码的复杂度为O(n²),其中n是输入序列的长度。它使用了嵌套循环,这些循环不断地遍历序列元素。

空间复杂度

代码的空间复杂度取决于代码的输入序列和用于处理它们的变量。

输入序列

输入序列字符串占用O(n)空间,其中n是序列长度。

附加变量

代码中有一个布尔变量 foundPair,用于确定是否遇到连续的1对。它还使用一个名为iterations的整数变量来跟踪迭代次数。

这些变量占用O(1)常数空间。

函数调用堆栈

另一方面,该算法不包含递归调用,也没有大的函数调用堆栈使用,因此函数调用引起空间复杂度微不足道。

代码的空间复杂度为O(n),其中n是输入序列长度。它仅由输入序列本身引起。添加了其他参数是常数因子,对总空间复杂度没有太大影响。

方法-2:堆栈方法

堆栈方法”是一种通过将二进制数字序列中的1的数量转换为0来确定比赛胜利者的方法。该方法使用堆栈数据结构来维护已记录的'1'的索引。在序列探索过程中,每个遇到的'1'都会被推送到堆栈列表中。当找到重复的'1'时,会从堆栈中弹出它们的索引,并将序列中的字符替换为'0'。

这种处理会一直进行,直到不再生成相邻的'1'对。堆栈策略允许更精确的游戏规则扫描,这对于复杂的游戏至关重要。这种将扫描和更新步骤分开的方法本身就简化了逻辑并提高了代码模块化。时间复杂度由元素数量和'1'的对数决定,而堆栈的大小(相对于'1'的数量)决定了空间复杂度。

程序

输出

Enter the sequence of 0s and 1s: 1101001001
Final sequence: Converting pair of consecutive 1s at indices 0 and 1 to 0s.
Converting pair of consecutive 1s at indices 3 and 6 to 0s.
Player 2 wins!
Total iterations: 2
0000000001

说明

  • 函数 determineWinner()

该函数以字符串序列作为参数,该序列表示游戏的初始状态。它初始化一个堆栈(std::stack<int> indexStack)来跟踪'1'的位置。它会遍历序列,将'1'的索引推送到堆栈。

如果找到连续的两个'1',它会移除堆栈中先前添加的索引,将链接的元素更改为'0',并增加迭代计数器。最后,它会检查是否还有剩余的'1'来确定谁是赢家:如果没有'1',则玩家1获胜,否则玩家2获胜。最终,它返回转换后的序列。

  • 主函数

在 main () 函数中,用户必须输入0和1的初始序列。

最后,将序列作为输入变量调用 determineWinner() 函数,并将最终序列打印到控制台。该代码有效地利用堆栈数据结构来保留遇到的'1'的索引,并找出连续的'1'对。

它显示了信息丰富的控制台输出,反映了将连续的'1'对替换为'0'的过程以及获胜方。 determineWinner() 函数负责游戏逻辑,main() 函数负责用户交互。

复杂度分析

时间复杂度

遍历序列

代码在 determineWinner() 函数中作为一个单一的for循环运行,该循环负责在整个程序中仅处理一次输入序列。

每次循环的持续时间通常导致O(n)时间,其中n表示原始序列的长度。

栈操作

该循环通过推入和弹出机制执行在堆栈中移除和放置项目的操作任务。

堆栈操作的平均复杂度为O(1),前提是这些和其他操作(例如,deque)是常数时间。

但是,根据“1”在数字中的出现次数,堆栈操作的数量最多可以达到O(n),即输入数字的数量。

查找连续对

根据基于堆栈的机制,必须检索序列的连续'1'对。这些检查方法的​​时间复杂度为O(1),因为它们基本上只是比较以及通过索引号访问元素。

考虑到这些因素,代码的时间复杂度将为O(n),其中n是输入序列的长度。

空间复杂度

堆栈空间

堆栈的空间复杂度取决于堆栈中元素的数量,其最坏情况下的电阻率最低,最坏情况可以为O(n),其中n是输入序列的长度。

其他变量

在代码的情况下,迭代变量(一个整数)起到了记录迭代的作用。因此,代码的总体空间复杂度为O(n),其中n是输入序列。