Java 执行一组操作后,检查给定的布尔数组是否与目标布尔数组匹配

Java 执行一组操作后,检查给定的布尔数组是否与目标布尔数组匹配,java,arrays,boolean,Java,Arrays,Boolean,这个任务实际上是作为家庭作业交给我们的,但是家庭作业中的要求是写一个递归方法,如果数组a可以匹配数组B,那么这个方法可以返回true或false。在我们对数组a执行了几个步骤之后,我已经以递归的方式回答了这个问题,我感兴趣的是,是否有一种更聪明的方法,一种特定的模式或方程式,可以用来解决这类任务, 尽管如此,我不确定家庭作业标签是否仍然相关,但我添加了它以防万一 详情如下: 给定两个长度相同的布尔数组。如果给定数组“init”可以与目标数组“target”匹配,则返回true, 问题是:每当我们

这个任务实际上是作为家庭作业交给我们的,但是家庭作业中的要求是写一个递归方法,如果数组a可以匹配数组B,那么这个方法可以返回true或false。在我们对数组a执行了几个步骤之后,我已经以递归的方式回答了这个问题,我感兴趣的是,是否有一种更聪明的方法,一种特定的模式或方程式,可以用来解决这类任务, 尽管如此,我不确定家庭作业标签是否仍然相关,但我添加了它以防万一

详情如下: 给定两个长度相同的布尔数组。如果给定数组“init”可以与目标数组“target”匹配,则返回true, 问题是:每当我们将一个索引的值从true“翻转”到false,反之亦然,索引中的值也会翻转到当前索引的左右两侧(当然,如果这样的索引在数组边界内),例如:

boolean[] init =   {true, false, true, false, true, false};
boolean[] target = {false, true, false, true, false, true};
在这种情况下,答案是正确的,因为我们可以翻转init数组的第一个点[0],结果是:

boolean[] init =   {false, true, false, false, true, false);
boolean[] target = {false, true, false, true, false, true};
然后翻转init数组中的第四个点[3],使init数组和目标数组匹配:

boolean[] init =   {false, true, false, true, false, true};
boolean[] target = {false, true, false, true, false, true};
递归地,它只是测试“翻转状态”或没有“翻转状态”的两个选项,并在每个测试的数组索引中前进,这将递归地检查所有选项,如果找到匹配项,最终返回true

现在回到我的问题上,有没有更好的方法来解决这类问题,而不必检查这么多选项?它不必是递归的。。。事实上,如果不是这样,那可能是最好的:) 因此,请随时分享您的想法和建议


谢谢

好的,我不打算写一个实现,但这里是基本逻辑。找出哪些值需要更改,例如{true,false,false,true}与{true,true,false,false}={true!=true,false!=true,false!=false!=false}={false,true,false,true}

现在,我们将尝试翻转这个新数组,直到从0到(size-2)的所有值都等于false。我们知道我们可以做到这一点。如果[0]==true,则在[1]处翻转;如果[1]==true,则在[2]处翻转。只需逐级检查每个值,大小为-2


最终,整个数组将为false,除了最后一个值为true或false。现在的问题是,如果只有最后一个值为真,是否可以转换数组,使所有值都为假

如何加快实现(对于是否可以使用给定规则转换数组的问题回答是/否):

  • 将所有内容表示为位,而不是真值和假值数组。那么位翻转模式是:1100…00,1110…00,0111…00,…,0000…11。我们将搜索位翻转模式通过执行BFS(或DFS)转换数组的所有可能方式

  • 存储是否可以使用位集(如果语言允许此类低级实现或提供此类库)或字符/布尔数组进行转换。这将减少转换使用的空间。数组/位集的大小为2^n

  • 当您获得了所有可能的转换后,您可以通过对输入和目标进行XOR运算,用O(1)中固定数量的元素来回答这个问题,然后检查这种转换是否存在。嗯,如果元素的数量不同,那么就没有什么优势了

它应该能够达到20到23位,同时保持时间在1-3秒(假设C++代码)。对于Java,它可能稍微慢一点,但应该在30秒以下

不过,时间复杂度并不比您当前的方法好

您还可以搜索转换模式0000…01(提前终止,而不是搜索可能转换的整个空间),然后使用Darcy Rayner建议的方法。最坏情况的复杂性并不比您当前的方法好

我不知道这个问题是否有数学上的解决办法。目前,这一切都是蛮力

编辑

从数学上讲,我们可以用达西·雷纳(Darcy Rayner)建议的方法(通过分析最后2位)证明我们可以贪婪地将差值减少到最多1

也可以证明,任何时间,我们都可以否定整个模式,即长度3K,平凡,长度3K+ 1,两端翻转,中间3组,长度3K+ 2,一端翻转,中间3组。 因此,如果最后一位=1,我们可以翻转整个模式。如果原始长度为3k+1,则最终会得到3k差(true),可以简单地翻转。如果原始长度是3k,我们最终得到3k-1的差异,我们可以在一端翻转,每3组翻转一次。在这两种情况下(长度3k+1和长度3k),变换总是可能的

我目前没有关于3k+2案例的反证。

评论

对于n位,可以有n个操作用于不同的更改

  • 操作的顺序是不相关的!(交换的,结合的)
  • 执行两次操作将恢复相同的状态。(反思性)
因此,每个解都是n个操作的子集,以任何顺序执行

  • 与算法无关:如果有k>4个连续不变位,则中间位在[i+2]到[k-1-2]之间的操作可以排除
  • 最多3次操作影响特定位。因此,对于所有不同的位,您可以收集要从中选择的操作
  • 必须选择一位的3个操作中的1个或3个操作(2个操作将恢复该操作)
你为什么不试试看