【问题标题】:Print all contiguous subarray打印所有连续子数组
【发布时间】:2020-06-24 12:16:11
【问题描述】:

我想编写一个递归函数来将所有连续的子数组添加到一个列表中。 该功能有效,但有一些重复。我想知道是否有办法避免这种情况。

def numSubArray(array, result):
    if len(array) == 0:
        return []
    result.append(array)
    numSubArray(array[1:], result)
    numSubArray(array[:-1], result)
    return result

【问题讨论】:

  • 请修正你的缩进。
  • 同时修改result(称为副作用)和返回result并不是一个好的功能设计。像sortedlist.sort一样,通常选择其中之一。
  • 你能解释一下这个函数背后的推理/逻辑吗?

标签: python recursion sub-array


【解决方案1】:

迭代方法:使用生成器函数

你也可以使用生成器来产生所有可能的连续子数组:

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]))

【讨论】:

    【解决方案2】:

    解决方案 1. 暴力递归并删除重复项

    您可以使用set 消除重复。
    但是你不能使setlists 因为list 是不可散列的。
    为了提高效率,你可以先收集索引对,然后切片:

    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])))
    

    输出:

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

    解决方案 2. 无冗余递归

    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])))
    

    输出:

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

    实际上,解决方案 2 的 num_sub_array 有一个尾递归。所以你可以把它改成循环。

    解决方案 3. 循环

    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])))
    

    输出:

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

    我使用sorted 来比较两种方法。没必要。

    【讨论】:

      【解决方案3】:

      您的代码似乎会生成以下内容以生成非空array 的所有子序列:

      1. array(即包含两个array 中的第一项和最后一项的所有子序列)
      2. array[1:] 的所有子序列(即所有的子序列都包含array 中的第一项
      3. array[:-1] 的所有子序列(即所有的子序列都包含array 中的最后一项

      所以重复的来源很清楚:array 中既没有第一项也没有最后一项的任何子序列将被计算两次(在任何给定的调用中,这意味着 array 越长,您可以复制的越多得到)。

      希望解决方案也很明确;删除#1(后面会介绍)和

      • 替换 #3 将所有 包含array 中的第一项的子序列,或
      • 用所有确实包含array中最后一项的子序列替换#2

      【讨论】:

      • 我不明白#1 和#2/#3 我需要用numSubArray(array[1:-1], result) 替换第一个或第二个递归调用?
      • 否;请参阅关于#1 的编辑。而numSubArray 不保证这些需要。
      • 对不起,我真的不明白我需要如何更改算法的代码/愿景?
      【解决方案4】:

      你有一个数组作为输入,你想返回一个包含这个数组中所有值的列表,最好使用递归函数?

      我想你想要这个:

      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)
      

      最后一行将打印您列出的数组!

      【讨论】:

      • isinstance(i, list) 代替type(i)==list 怎么样?
      猜你喜欢
      • 1970-01-01
      • 2021-06-05
      • 2020-12-02
      • 2020-09-18
      • 2017-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-05
      相关资源
      最近更新 更多