HackerRank 上的一维数组游戏

Posted

技术标签:

【中文标题】HackerRank 上的一维数组游戏【英文标题】:1D array game on HackerRank 【发布时间】:2016-05-24 19:17:49 【问题描述】:

我试图在 HackerRank 上解决这个问题几个小时。基本问题陈述如下:

您有一个仅由 0s 和 1s 组成的一维数组。您从第 0 个索引开始。 让我们假设数组的大小为n。如果您可以超出数组的范围(即索引> n-1),您将获胜。但你只能通过两种方式移动:

向前或向后走一步。 向前跳跃正好 'm' 长度。

另外,您只能踩到值为 0 的元素。 第 0 个索引处的值已知为 0。(因此您从有效位置开始)

'm' 作为输入提供,它可以是 0 到 100 之间的任何值(包括 0 到 100)。 数组大小可以是 2 到 100 之间的任何值。

如果有可能获胜,程序应该打印“YES”。否则“否”。

我尝试使用 Java 中的回溯算法来解决它。但它在大多数测试用例中都会被拒绝。

请帮助我。提前致谢。

public class Solution 

public static void main(String[] args) 
      Scanner sc = new Scanner(System.in);

         int n=sc.nextInt();
         int m=sc.nextInt();
         int[] array = new int[n];

         for(int i=0;i<n;i++)
             array[i]=sc.nextInt();
         

         if(m<2)
             for(int i=0;i<n;i++)
                  if(array[i] == 1)
                        System.out.println("NO");
                        break;
                     
                
                System.out.println("YES");
            

            else
        if(isSolvable(array,0,m,n))  
        System.out.println("YES");
        else 
        System.out.println("NO");

        

    

    static boolean isSolvable(int[] array,int x,int m,int n)
        if(x>n-1) 
            //System.out.print(x + " "); 
            return true;
        
        if(array[x] == 1) return false;
        if(isSolvable(array,x+m,m,n))
            //System.out.print(x + " "); 
            return true;
        
        if(isSolvable(array,x+1,m,n))
            //System.out.print(x + " "); 
            return true;
        
        return false;
      
 

【问题讨论】:

【参考方案1】:

我没有通过回溯来执行此操作,而只是递归,我能够解决问题并使所有测试用例都正确。您发布的代码也不会进行任何回溯。我还看到,在您的条件下,您缺少向后移动 1 的条件,这会导致您在某些情况下失败。

例如:0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1,m=5。

用上面的例子,先跳到x+m,然后再尝试x+m,再尝试x+1,否则出局。

分解这个测试用例:

0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1

          ^ x+m True
0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1

                    ^ x+m False
0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1

            ^ x+1 False
0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1

  ^ x+1 False

使用您的代码,您将返回 false where 而要解决此问题,您需要执行以下操作:

0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1

          ^ x+m

0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1

        ^ x-1
0 1 1 1 0 0 1 1 1 0 1 1 1 1 0 1

                  ^ x+m

然后再两个 x+m 完成它以返回 true。

要使用您的代码完成此操作,您需要添加条件以向后移动一个空格,但是这样做时,您可以合并一个无限递归循环,例如:(-1+1-1+1-1+1)这将导致堆栈溢出。我建议包括的其中一件事是boolean 数组,用于保存您以前见过的地点的记忆。

【讨论】:

你解释的那个测试用例完全有帮助。我根本没有想到它。非常感谢。我只是在我的函数中添加了向后移动一个空格的条件,并将位置的值从 0 更改为 1,以将其标记为已访问的地点。成功了。【参考方案2】:

编码这个游戏对于业余爱好者来说有点困难,但可以解释我认为可以解决问题的算法。

首先,我认为你可以同时走一个和“m”步的点是这个问题的关键点。我的意思是你可以从他们那里选择另一种方式。如果您到达它们 3 次,那么它们就没有用了,等等。我认为将它们放在一个数组中很重要。

定义一个数组为WellPoints

检查数组的第一个点,您可以在该点上走一步,然后再走“m”步。另存为firstWellPointWellPoints[0]

尝试使用简单的回溯算法通过一个或“m”步到达这一点。如果你不能,那只是“不”。

如果您可以访问firstWellPoint,请定义counter 以计算您访问WellPoints 的次数。

在检查每个点的后续步骤时,还要检查点是否适合单步和 m 步。如果一个和 m 进一步都是“0”,则将其放置到 WellPoints 数组中。

现在,如果下一次检查不成立,请返回 WellPoints 数组的最后一个元素,并将 counter 提高 1。

找到新的WellPoint 后,将counter 重置为1。

如果counter = 3,则删除此WellPoint并以其他方式从其前一个重新开始检查,这意味着WellPoint数组的新最后一个元素。它可以通过检查counter来决定方式,例如如果counter=1尝试一步,当您再次来到这里时,这意味着如果counter=2尝试m步。

如果 WellPoint 数组的第一个元素,或 firstWellPoint 如我所解释的那样通过在 WellPoint 数组上回溯 3 次再次到达,您也将删除此 WellPoint,因此您的数组将无法走到尽头。

如果您到达数组末尾,那么您就知道...

【讨论】:

以上是关于HackerRank 上的一维数组游戏的主要内容,如果未能解决你的问题,请参考以下文章

使用一维数组和for循环的C语言字符猜谜游戏

如何在一维数组中“扁平化”或“索引” 3D数组?

一维 NumPy 数组上的滑动标准差

0511 二维数组定义

LeetCode 507. 完美数 / 2022. 将一维数组转变成二维数组 / 390. 消除游戏(等差数列模拟,约瑟夫环)

Java二维数组的概念和使用方法