Interview Question
Country: United States
Search all options but do not revisit states (position, speed).
unordered_set<pair<int, int>> visited;
bool CanCross(vector<bool> field, int i, int speed) {
if (i >= field.size())
return true;
pair<int, int> state(i, speed);
if (!field[i] || speed <= 0 || visited.count(state))
return false;
visited.insert(state);
return CanCross(field, i+speed, speed)
|| CanCross(field, i+speed+1, speed+1)
|| CanCross(field, i+speed-1, speed-1);
}
bool CanCross(vector<bool>& field, int index, int velocity,
vector<vector<bool>>& cache) {
if (index >= field.size())
return true;
if (!field[index] || velosity <= 0 || cache[index][velocity])
return false;
cache[index][velocity] = true;
return CanCross(field, index+velocity, velocity) ||
CanCross(field, index+velocity+1, velocity+1) ||
CanCross(field, index+velocity-1, velocity-1);
}
Here's a solution is python. Pretty easy to understand
def canCrossHelper(path, v, index):
if index >= len(path):
return True
if v <= 0:
return False
if path[index] == False:
return False
if canCrossHelper(path, v+1, index + v + 1) or canCrossHelper(path, v-1, index + v - 1) or canCrossHelper(path, v, index + v):
return True
return False
def canCross(path):
return canCrossHelper(path, 1, 0)
That approach is too slow for big inputs. You should not revisit the same search states (index, v)
True. Added memoization:
def canCrossHelper(path, vp, answersArr):
if vp[1] >= len(path):
return True
if vp[0] <= 0:
return False
if path[vp[1]] == False:
return False
tup = (vp[0] + 1, vp[1] + vp[0] + 1)
if tup not in answersArr:
answersArr[tup] = canCrossHelper(path, tup, answersArr)
tup2 = (vp[0], vp[1] + vp[0])
if tup2 not in answersArr:
answersArr[tup2] = canCrossHelper(path, tup2, answersArr)
tup1 = (vp[0] - 1, vp[1] + vp[0] - 1)
if tup1 not in answersArr:
answersArr[tup1] = canCrossHelper(path, tup1, answersArr)
if answersArr[tup] or answersArr[tup1] or answersArr[tup2]:
return True
return False
def canCross(path):
return canCrossHelper(path, (1,0), dict())
I just use recursion plus memoization, by using a HashSet to store all the (index, velocity) pairs I have seen.
import java.util.*;
class CrossArray {
private static HashSet<String> visited = new HashSet<String>();
public static boolean canCross(boolean arr[]) {
return canCrossHelper(arr, 0, 1);
}
public static boolean canCrossHelper(boolean arr[], int index, int velocity) {
String key = "" + index + "-" + velocity;
if(visited.contains(key))
return false;
for(int v=velocity-1; v<=velocity+1; v++) {
if(v == 0)
continue;
int newIndex = v+index;
if(newIndex >= arr.length)
return true;
if(arr[newIndex] && canCrossHelper(arr, newIndex, v))
return true;
}
visited.add(key);
return false;
}
public static void main(String[] args) {
boolean arr[] = new boolean[]
{true, true, false, true, false, true, false, false, false, true};
boolean arr2[] = new boolean[]
{true, true, false, true, false, true, true, false, false, true, false};
System.out.println(canCross(arr));
System.out.println(canCross(arr2));
}
}
Here is C# Code
public static void VelocityJump()
{
bool[] just = { true, true, false, true, false, true, true, false, false, true, false };
int velocity = 1;
for (int i = 0; i < just.Length; i += velocity)
{
if (i == just.Length - 1 || i + velocity == just.Length - 1 || i + velocity + 1 == just.Length - 1)
{
Console.WriteLine("Rabbit can cross");
break;
}
if (!just[i] || i + (velocity - 1) >= just.Length || i + velocity >= just.Length)
{
Console.WriteLine("Rabbit can not jump");
break;
}
if ((i+velocity+1 < just.Length) && (just[i + velocity + 1]))
velocity++;
else if ((i+velocity<just.Length) && !just[i+velocity])
{
if (i != 0) velocity--;
}
}
}
It's a Dynamic Programming problem with recursive function as
CanReach(i,j) = { true if stone[i] is true && (CanReach[i-j][j-1] || CanReach[i-j][j] ||CanReach[i-j][j+1])
where,
i is the stone
j is the velocity when the frog reached i
- Brandy May 26, 2014