HackerRank上的一维阵列游戏

时间:2016-05-24 19:17:50

标签: java arrays backtracking

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

你有一个只包含0和1的1D数组。你从第0个索引开始。 让我们假设数组的大小为n。如果你能超越数组的范围(即索引> n-1),你就赢了。但是你只能以两种方式行动:

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

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

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

如果可以获胜,程序应打印“是”。否则“不”。

我尝试使用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;
    }  
 }

2 个答案:

答案 0 :(得分:0)

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

首先,我认为你可以进行一步和“m”步骤的要点是这个问题的关键点。我的意思是你可以选择另一种方式。如果你达到它们3次,那么它们就没用了等等。我认为把它们放在一个阵列中是很重要的。

  • 将数组定义为WellPoints

  • 检查阵列的第一个点,您可以前进一步,“m”再进一步。将其另存为firstWellPointWellPoints[0]

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

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

  • 在检查每个点的后续步骤时,还要检查点是否适合一步并且m步两者。如果对于两者都进一步为“0”,则将其放置到WellPoints数组。

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

  • 当您找到新的WellPoint时,请将counter重置为1.

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

    < / LI>
  • 如果WellPoint数组第一个元素,或者firstWellPoint,如我所解释的那样,通过回溯WellPoint数组3次再次到达,您也会删除此WellPoint所以你的阵列将无法走到最后。

  • 如果你到达阵列的末尾,那么你知道......

答案 1 :(得分:0)

我没有使用回溯,但只是递归,我能够解决问题并使所有测试用例都正确。您发布的代码也不会进行任何回溯。我也看到,在你的条件下,你错过了向后移动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而不是解决此问题,您需要执行以下操作:

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)这将导致stackoverflow。我建议包括的一件事是boolean数组,用于记忆你以前见过的斑点。