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”步。另存为firstWellPoint
或WellPoints[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 上的一维数组游戏的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 507. 完美数 / 2022. 将一维数组转变成二维数组 / 390. 消除游戏(等差数列模拟,约瑟夫环)