我正在尝试解决this problem,并且通过了5个测试用例,但是有些测试用例失败了,我无法弄清楚算法中的问题是什么。尽管我尝试了来自失败的测试用例的一些测试数据,但大多数都正确无误,但我认为其中一些不正确,从而导致算法失败。因此,如果有人能对实现此算法的正确方法有所了解,那将非常有帮助,或者我在实现过程中哪里出了问题。
我的算法:
1. Index for the move is at index '0' of string (say moving index)
2. Loop over the string starting with index '1' of string:
2.1. check if (moving index + leap) can outrun the array:
2.2. If not then, check whether the character is 1 or 0 :
2.2.1 Check for the number of '1's that are continuous, if they exceed the leap value then return false (as anyway we will not be able to jump).
2.2.2 If its 0, then check whether its a zero after continuous '1's.
If not so, continue moving forward one step at a time.
If so, first try to skip over those continuous '1's by checking whether (moving index + leap) is allowed or not as per the rule.
If not allowed, check in a while loop till what point we can move backwards one step at a time to get (moving index + leap) to satisfy.
If not possible, return false.
我不知道这是否是解决此类问题的有效方法,非常感谢其他可能的方法。
代码:
import java.util.*;
public class Solution {
public static int leapStep(int index,int leap,int len,int[] game){
if(game[index+leap]==0){
index += leap;
}
return index;
}
public static boolean canWin(int leap, int[] game) {
int index = 0;
int len = game.length;
int consecutiveLength=0;
for(int i=1;i<len;){
if(index+leap>len-1){
return true;
}
if(game[i]==1){
consecutiveLength++;
if(consecutiveLength>=leap){
return false;
}
i++;
}else{
if(consecutiveLength==0){
index =i;
i++;
}else{
if(index+leap<=len-1){
int tryLeap = leapStep(index,leap,len,game);
if(index < tryLeap){
index = tryLeap;
tryLeap =0;
i = index+1;
}else if(index>0 && game[index-1]==0 ){
boolean notViable = false;
while(index>0){
if(game[index-1]!=0)
return false;
index -= 1;
i = index+1;
tryLeap = leapStep(index,leap,len,game);
if(index<tryLeap){
index = tryLeap;
i = index+1;
tryLeap=0;
notViable = false;
break;
}
else{
notViable = true;
}
}
if(notViable){
return false;
}
}else{
return false;
}
}
consecutiveLength=0;
}
}
}//closing for
return true;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int q = scan.nextInt();
while (q-- > 0) {
int n = scan.nextInt();
int leap = scan.nextInt();
int[] game = new int[n];
for (int i = 0; i < n; i++) {
game[i] = scan.nextInt();
}
System.out.println( (canWin(leap, game)) ? "YES" : "NO" );
}
scan.close();
}
}
答案 0 :(得分:2)
对我来说,更好的方法是按以下方式递归解决此问题(它通过了所有测试):
y
在下面的输入中,显示了几对线。每对的第一个元素代表public static boolean canWin(int[] array, int index, int leap) {
// the only case when we lose
if (index < 0 || array[index] > 0) {
return false;
}
// if you're standing in the last entry or (index + leap) >= array.length then win
if ((index >= array.length - 1) || ((index + leap) >= array.length)) {
return true;
}
// mark it as visited so that not to iterate over it again
array[index] = 1;
// check all 3 conditions then recursively again
return canWin(array, index + 1, leap) || canWin(array, index - 1, leap) || canWin(array, index + leap, leap);
}
,第二个元素代表数组。
输入:
3
0 0 0 0 0
5
0 0 0 1 1 1
3
0 0 1 1 1 0
1
0 1 0
输出:
true
true
false
false
说明:
假设您当前的职位是leap
。
index
,那么游戏将会失败。如果它是最后一个位置,或者0
至少达到数组的长度,那么根据定义,游戏将获胜。 index + leap
或index - 1
或index + 1
。因此,您对后面的每个索引重复步骤1,并取index + leap
的结果,因为找到一条路径就足够了。不要忘记将单元格的值设置为1,因为第二次访问该单元格没有意义-我们不想一遍又一遍地重复相同的动作而崩溃。答案 1 :(得分:1)
您的伪代码看起来不错,但是您的代码中有一些错误,这可能是造成麻烦的原因。
if(index+leap<=len-1)
毫无用处,您可以在不修改算法行为的情况下将其删除。之所以如此,是因为您已经在循环的第一行中对其进行了检查,并输入了else
关键字。index
和i
的内容。读完几遍后,它们的含义对我来说还不清楚,它们看起来也一样。这可能会引起麻烦,因为在对index
的调用中使用了变量leapStep
,但是index
通常落后于i
。令人困惑。我没有找到代码失败的示例。
这是我接受HackerRank的解决方案。这是一个迭代的过程,接近您的。它的原理很简单:从位置0开始,随着我们逐步增加位置,跟踪您有权使用的位置(在变量memoTab
中,我尽可能地删除了dp
名称令人恐惧的):如果我们处于以前已经达到的位置,那么我们可以转到+1或+跨越。
如果不允许它回溯并反向移动就足够了。为了解决这个问题,每当达到1时,我都会将下一个0保留在内存中。如果遇到一个我可以立即到达的位置,我会回到该0并说可以去那里。
这是代码,首先是一个小辅助函数,如果游戏结束,该函数将返回true
。给定一个游戏和一个索引,它表示是否可以转到该索引并将其写入备忘录。
public static boolean check(int[] game, boolean[] memo, int index){
if(index >= 0 && index < game.length){
if(game[index] != 1){
memo[index] = true;
}
}
return index >= game.length;
}
这是求解器函数,它首先读取值,然后开始循环。
public static void solveOne(){
int n = sc.nextInt();
int leap = sc.nextInt();
int[] game = new int[n];
for (int i = 0; i < n; i++) {
game[i] = sc.nextInt();
}
int index = 0;
boolean[] memoTab = new boolean[n];
for (int i = 0; i < n; i++) {
memoTab[i] = false;
}
memoTab[0] = true;
boolean rememberIndex0 = false;
boolean gotoIndex0 = false;
int index0 = 0;
boolean finished = false;
我们完成了初始化,让我们循环:
while(index < game.length){
// we encounter the first 0 after some 1, keep it in memory !
if(rememberIndex0 && game[index] == 0){
index0 = index;
gotoIndex0 = true;
rememberIndex0 = false;
}
// this index is an index we reached before, we can continue from here
if(memoTab[index]){
// we previously said we need to go back to a lower position
if(gotoIndex0){
gotoIndex0 = false;
index = index0;
memoTab[index] = true;
continue;
}
// it's finished if either is true
finished = check(game, memoTab, index + 1)
|| check(game, memoTab, index + leap);
if(finished) break;
}
// if this position is a 1, then we will keep in memory the next 0
if(game[index] == 1){
rememberIndex0= true;
}
// don't forget incrementing
index += 1;
}
System.out.println(finished?"YES":"NO");
}