2

I want to write a recursive function to add all of the contiguous subarrays in a list. The function works but there is some duplication. I wanted to know if there is a way to avoid this.

def numSubArray(array, result):
    if len(array) == 0:
        return []
    result.append(array)
    numSubArray(array[1:], result)
    numSubArray(array[:-1], result)
    return result
David Buck
  • 3,752
  • 35
  • 31
  • 35
Raphael00
  • 61
  • 1
  • 9

4 Answers4

1

solution 1. brute-force recursion and remove duplicates

You can eliminate duplications using set.
But you cannot make set of lists since list is not hashable.
And for efficiency, you can gather index-pairs first, and then slice:

def num_sub_array(array):
    return [
        array[i:j] for i, j in build_pair_set(0, len(array))
    ]


def build_pair_set(start: int, end: int) -> set:
    return set() if start == end else (
        {(start, end)}
        | build_pair_set(start + 1, end)
        | build_pair_set(start, end - 1)
    )


print(sorted(num_sub_array([1, 2, 3, 4])))

output:

[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2], [2, 3], [2, 3, 4], [3], [3, 4], [4]]

solution 2. recursion without redundancy

def num_sub_array(array):
    if not array:
        return []
    return [array[i:] for i in range(len(array))] + num_sub_array(array[:-1])


print(sorted(num_sub_array([1, 2, 3, 4])))

output:

[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2], [2, 3], [2, 3, 4], [3], [3, 4], [4]]

Actually, solution 2's num_sub_array has a tail recursion. So you can change it to loop.

Solution 3. Loop

def num_sub_array(array):
    return [
        array[i:j]
        for i in range(len(array))
        for j in range(i + 1, len(array) + 1)
    ]


print(sorted(num_sub_array([1, 2, 3, 4])))

output:

[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2], [2, 3], [2, 3, 4], [3], [3, 4], [4]]

I used sorted for comparing two methods. It is not necessary.

Boseong Choi
  • 2,566
  • 9
  • 22
0

Your code appears to produce the following to produce all subsequences of a non-empty array:

  1. array (that is, all subsequences that include both the first and last items in array)
  2. all subsequences of array[1:] (that is, all subsequences that do not include the first item in array
  3. all subsequences of array[:-1] (that is, all subsequences that do not include the last item in array

So the source of the duplication is clear: any subsequence that has neither the first nor the last item in array will be counted twice (in any given call, meaning the longer array is, the more copies you can get).

The solution, hopefully, is also clear; remove #1 (it will be covered by what follows) and either

  • replace #3 will all subsequences that do include the first item in array, or
  • replace #2 with all subsequences that do include the last item in array
Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
0

You have an array as input and you want to return a list with all the values in this array, preferably using a recursive function?

I think you want this:

new_list = []
def array_to_list(arr): 
     for i in arr: 
         if isinstance(i,list) or isinstance(i,array.array): 
             array_to_list(arr) 
         else: 
             new_list.append(i)
a = arr.array('d',  [1.1, 3.5, 4.5])
array_to_list(a)
print(new_list)

The last line will print your listed array!

Martijniatus
  • 102
  • 3
0

Iterative Approach: using generator function

you can also use generator to yield all possible continuous subarray:

from typing import List


def brute_force(nums: List[int]) -> int:
    i = j = 0
    while j <= len(nums) and i <= len(nums):
        yield nums[i:j+1]
        j += 1
        if j == len(nums):
            i += 1
            j = I

list(brute_force([1, 2, 3, 4]))