Search code examples
pythonalgorithmrecursionbacktracking

Return immediately for recursive calls


Problem Statement: You are given an integer array nums. You are initially positioned at the array's first index, and each element in the array represents your maximum jump length at that position. Return true if you can reach the last index, or false otherwise.

How can I change my code so that it returns immediately when I have found a path that works for this problem instead of going through all the recursive calls that I have made previously

def canJump(self, nums: List[int]) -> bool:
    solve = [False]
    def backtrack(i):
        if solve[0] == True:
            return
        
        if i == len(nums)-1:
            solve[0] = True
            return
        
        if i >= len(nums) or nums[i] == 0:
            return
        
        for x in range(1, nums[i]+1):
            backtrack(i+x)
    
    backtrack(0)
    return solve[0]

Solution

  • General Form of a Recursive Function

    The general form of a recursive function has two mutually exclusive types of conditions that can be met on each iteration of the recursion. These are either:

    1. terminal conditions, or
    2. non-terminal conditions.

    Both types of condition contain a return statement.

    Terminal Conditions

    The return statement in terminal conditions typically takes the form return <value>.

    The solution to the problem you are trying to solve requires two possible terminal conditions:

    1. The case where you know you can reach the last index. return True
    2. The case where you know you can NOT reach the last index. return False

    Non-Terminal Conditions

    The non-terminal condition will occur on iterations where neither of the terminal cases are met. In this situation, you will call the recursive function and return what it returns.

    This answer covers terminal and non-terminal conditions in more detail.

    Example

    Consider a recursive function that sums the numbers of an array.

    def sum(position, array, end):
        if(position == end): # terminal condition
            return 0 
        else: # non-terminal condition
            return array[position] + sum(position+1, array, end) 
    

    Another Example

    Depending on any constraints to your problem that I might have missed, a solution might be the following:

    def jump(current_position, nums, finish_line):
        """
        greedy algorithm: 
        choose the next position with the largest sum of (jump_range + index)    
        """
        jump_range = nums[current_position]
        choice = current_position + jump_range
    
        if(jump_range == 0): # terminal condition
            return False 
        if(choice >= finish_line): # terminal condition
            return True 
        else: # non-terminal condition
            utility = 0
            
            for next_position in range(current_position+1, jump_range+1):
                next_jump_range = nums[next_position]
                
                if(utility <= next_position + next_jump_range):
                    utility = next_position + next_jump_range
                    choice = next_position
            
            return jump(choice, nums, finish_line)
    
    
    input1 = [2,0,0,10,3]
    input2 = [2,3,0,10,3]
    current_position = 0
    
    finish_line = len(input1)
    print(jump(0, input1, finish_line)) # False
    
    finish_line = len(input2)
    print(jump(0, input2, finish_line)) # True
    

    The most noteworthy difference from your solution is that return statements always return a value.