Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to check we can cross river by stones or not in Python
Suppose we have a list of sorted numbers called stones representing the positions of stones on a river that we are trying to cross. To cross the river, we must finish at the last stone. In each step, we can jump (k - 1, k, or k + 1) steps ahead where k is the distance of the last jump. We have to check whether we can cross the river or not.
So, if the input is like stones = [0, 1, 3, 4, 5, 6, 8, 9, 13], then the output will be True. We can start from 0, then jump 1 unit to reach stone 1, then 2 units to reach 3, after that 2 units to reach 5, then 3 units to reach 8, and finally 5 units to reach 13, which is the final destination.
Algorithm Steps
To solve this, we will follow these steps ?
- start := A[0], end := last element of A
- A := a set of all unique elements of A
- Define a function check(). This will take pos:= start, prev:= 0
- if pos is same as end, then
- return True
- for each jump in [prev − 1, prev, prev + 1], do
- if jump >= 1, then
- next_pos := jump + pos
- if next_pos is in A and check(next_pos, jump) is true, then
- return True
- if jump >= 1, then
- return False
- From the main method call check() and return result
Example
Let us see the following implementation to get better understanding ?
class Solution:
def solve(self, A):
start, end = A[0], A[-1]
A = set(A)
def check(pos=start, prev=0):
if pos == end:
return True
for jump in [prev - 1, prev, prev + 1]:
if jump >= 1:
next_pos = jump + pos
if next_pos in A and check(next_pos, jump):
return True
return False
return check()
ob = Solution()
stones = [0, 1, 3, 4, 5, 6, 8, 9, 13]
print(ob.solve(stones))
Output
True
How It Works
The algorithm uses recursive backtracking to explore all possible jump sequences. At each stone position, we try three possible jump distances: the previous jump distance minus 1, the same distance, or plus 1. We convert the stones list to a set for O(1) lookup time when checking if a landing position exists.
Alternative Approach with Memoization
For better performance with larger inputs, we can add memoization to avoid recalculating the same states ?
def can_cross_river(stones):
if not stones or stones[0] != 0:
return False
stone_set = set(stones)
end = stones[-1]
memo = {}
def dfs(pos, last_jump):
if pos == end:
return True
if (pos, last_jump) in memo:
return memo[(pos, last_jump)]
for jump in [last_jump - 1, last_jump, last_jump + 1]:
if jump > 0:
next_pos = pos + jump
if next_pos in stone_set and dfs(next_pos, jump):
memo[(pos, last_jump)] = True
return True
memo[(pos, last_jump)] = False
return False
return dfs(0, 0)
# Test the function
stones = [0, 1, 3, 4, 5, 6, 8, 9, 13]
print(can_cross_river(stones))
Output
True
Conclusion
The river crossing problem can be solved using recursive backtracking by exploring all valid jump sequences. Adding memoization improves efficiency by avoiding redundant calculations for the same position and jump distance combinations.
