【问题标题】:1D array game on HackerRankHackerRank 上的一维数组游戏
【发布时间】: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;
    }  
 }

【问题讨论】:

    标签: java arrays backtracking


    【解决方案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,因此您的数组将无法走到尽头。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-20
      • 1970-01-01
      • 1970-01-01
      • 2016-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多