简体   繁体   English

使用递归和无循环查找嵌套列表python的最小最大值

[英]find min max of nested list python using recursion and no loops

def min_max(L):

    if len(L) == 1:
        res = [L[0], L[0]]

    else:
        res = min_max(L[1:])

        if (L[0] < res[0]):
            res[0] = L[0]

        if (L[0] > res[1]):
            res[1] = L[0]

    return res

Here is my code that works for regular lists. 这是我的适用于常规列表的代码。 If there is only one element, that element is both the min and the max. 如果只有一个元素,则该元素既是最小值又是最大值。 Otherwise, we find the min and max for the elements in the list ahead of it, and then we compare, and swap if bigger or smaller. 否则,我们会在列表的前面找到元素的最小值和最大值,然后进行比较,并交换更大或更小的值。

I should do this for nested lists. 我应该对嵌套列表执行此操作。 What I tried doing was adding this line of code before the if len(L) == 1 case. 我尝试做的是在if len(L) == 1情况之前添加此代码行。

if isinstance(L[0],list):
    res = min_max(L[0])

elif len(L) == 1:
    res = [L[0], L[0]]

This works partially, but in examples like min_max([[3,2],4]) , returns [2,3] without considering the 4. How can I fix this? 这部分起作用,但是在min_max([[3,2],4])这样的示例中,返回[2,3]而不考虑4。如何解决此问题?

The following works for me: 以下对我有用:

def min_max(L):
    length = len(L)
    if length == 1:
        if isinstance(L[0],list): // sole element is a list, return its min & max
            return min_max(L[0])
        else:
            return [L[0], L[0]]   // otherwise it is both the min & max
    else:
        mid = length // 2
        result = min_max(L[:mid])  // find min and max of first half of list
        result2 = min_max(L[mid:]) // ditto for second half of list
        // now determine which of the two sets are the min and max of current list
        if (result2[0] < result[0]):
            result[0] = result2[0]
        if (result2[1] > result[1]):
            result[1] = result2[1]
        return result

Note that this cuts lists in half each time, rather than whittling them down by one element at a time. 请注意,这每次都将列表切成两半,而不是一次将列表缩减一个。 You still end up inspecting every element, but the number of calls on the stack grows proportionally to the log of the list lengths, so this version will work on pretty much any list of lists you could create, where yours will only work on lists with fewer than 1000 elements. 您仍然需要检查每个元素,但是堆栈上的调用数量与列表长度的对数成正比,因此此版本几乎可以在您可以创建的任何列表列表中使用,而您的列表仅适用于具有以下条件的列表:少于1000个元素。

If you're concerned about possibly empty lists or sublists: 如果您担心列表或子列表可能为空:

def min_max(L):
    length = len(L)
    if length > 1:
        mid = length // 2
        result = min_max(L[:mid])
        result2 = min_max(L[mid:])
        if (result2[0] < result[0]):
            result[0] = result2[0]
        if (result2[1] > result[1]):
            result[1] = result2[1]
        return result
    elif length == 1:
        if isinstance(L[0],list):
            return min_max(L[0])
        else:
            return [L[0], L[0]]
    else:
        return [float('inf'), -float('inf')]

You could simplify your code a bit by passing the current min & max as extra parameters. 您可以通过传递当前的min&max作为额外的参数来稍微简化代码。 Then your code basically needs to take care of three different scenarios: 然后,您的代码基本上需要照顾三种不同的情况:

  1. Given list is empty -> return min & max from parameters 给定列表为空->从参数返回最小值和最大值
  2. First element on the list is a list -> recurse with the nested list and min & max, then recurse with rest of the list 列表上的第一个元素是列表->使用嵌套列表和min&max递归,然后使用列表的其余部分递归
  3. First element on the list is number, update min & max and recurse with rest of the list 列表上的第一个元素是数字,更新最小值和最大值,然后用列表的其余部分递归

In practice the code would look like this: 在实践中,代码如下所示:

def min_max(L, minimum=float('inf'), maximum=-float('inf')):
    # Base case, return accumulated result
    if not L:
        return minimum, maximum

    if isinstance(L[0], list):
        # Element is a list, recurse with it
        minimum, maximum = min_max(L[0], minimum, maximum)
    else:
        # Element is a number, update current min & max
        minimum = min(minimum, L[0])
        maximum = max(maximum, L[0])

    # Process rest of the elements on the list
    return min_max(L[1:], minimum, maximum)

print(min_max([[3,2],4]))

Output: 输出:

(2, 4)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM