简体   繁体   English

使用递归检查两个未排序列表的元素和长度是否相等

[英]Check if the elements and length of two unsorted lists are equal using recursion

I am trying to write a purely recursive function that will return True if two unsorted lists are of the same length and contain the same elements. 我正在尝试编写一个纯递归函数,如果两个未排序的列表长度相同且包含相同的元素,则该函数将返回True。 I am not allowed to use any iteration, only recursion. 我不允许使用任何迭代,只能使用递归。 Here is an example of what it should do: 以下是应执行的操作示例:

>>> SameStuff(['Hello',1,2,3],[3,2,1,'Hello'])
True
>>> SameStuff(['HELLO',1,2,3],[3,'two',1,'Hello'])
False
>>> SameStuff([1,2],[])
False

I am struggling with the logic of my recursive function, and am missing some elements. 我为递归函数的逻辑而苦苦挣扎,并且缺少一些要素。 Here's what I have: 这是我所拥有的:

def SameStuff(list1,list2):
    if len(list1)!=len(list2):
        return False
    if #some base case:
        #return True?
    if list1[0] in list2:
        return SameStuff(list1[1:],list2)
    else:
        return False

I think you have most of the logic in the right place. 我认为您将大多数逻辑放在正确的位置。 You are just missing the case when both will be empty, by then presumably they were the same lists in different (potentially) orders! 您只是错过了两个都为空的情况,到那时,它们可能是相同的列表,但顺序不同(可能)!

Probably not efficient with the remove function, but tricky to pop the same elements from two different unordered lists. 使用remove函数可能效率不高,但是要从两个不同的无序列表中弹出相同的元素会比较棘手。

def SameStuff(l1, l2):
    if not l1 and not l2:
        return True

    if len(l1) != len(l2):
        return False

    last_element = l1[-1]
    if last_element not in l2:
        return False

    l1.remove(last_element)
    l2.remove(last_element)

    return SameStuff(l1, l2)
def SameStuff(list1, list2):

    # if both empty, they are equal
    if not list1 and not list2:
        return True

    # if unequal lengths, they are not equal
    if len(list1) != len(list2):
        return False

    # grab the first item from list1
    item = list1[0]

    # if it isn't in list2, they are not equal
    if item not in list2:
        return False

    # make copies so we don't disturb the original lists
    newlist1 = list1[:]
    newlist2 = list2[:]

    # remove the item from both copies
    newlist1.remove(item)
    newlist2.remove(item)

    # call ourself with the list copies
    return SameStuff(newlist1, newlist2)
def SameStuff(l1, l2):
    if l1 == []: return l2 == []    # if recursed down to empty lists -> True
    elif len(l1) != len(l2): return False   # if any length differences -> False
    elif l1[0] in l2: 
        i = l2.index(l1[0]) # identify index of first in l2 identical to l1[0]
        return SameStuff(l1[1:], l2[:i] + l2[i+1:]) # l2 without this element!
    else: return False

This works independent from order. 这与订单无关。 And also if there are multiple occurrences of some elements. 以及某些元素是否多次出现。

It is important to state that the missing base case in your code is test if both lists are empty. 重要的是要声明,如果两个列表都为空,则代码中缺少的基本案例是test。

The other important factor, is avoid to remove the found element from any of both received list, since that could alter them after the call. 另一个重要因素是避免从两个已接收列表中的任何一个中删除找到的元素,因为这可能在调用后更改它们。

This is the same code than yours, with the least modifications possible in my opinion: 这是与您的代码相同的代码,我认为修改最少:

def SameStuff(list1,list2):                                                   
    if len(list1)!=len(list2):
        return False
    if len(list1) == 0 and len(list2) == 0:
        return True
    if list1[0] in list2:
        list2b = list2[:]
        list2b.remove(list1[0])
        return SameStuff(list1[1:], list2b)
    else:
        return False


print(SameStuff(['Hello',1,2,3], [3,2,1,'Hello']))
print(SameStuff(['HELLO',1,2,3],[3,'two',1,'Hello']))
print(SameStuff([1,2],[]))

In order to not make any loop, you can add a parameter in the input of your function: 为了不造成任何循环,您可以在函数的输入中添加一个参数:

def SameStuff(list1,list2,i):
    if list1==[] and list2==[]:
        return True

    elif i>=len(list1):
        return False

    elif len(list1)!=len(list2):
        return False

    elif list1[i]==list2[0]:
        del list1[i]
        del list2[0]
        return SameStuff(list1,list2,0)
    else:
        return SameStuff(list1,list2,i+1)


print(SameStuff(["hello",1,4],[1,3,"hello"],0))
print(SameStuff(["hello",1,3],[1,3,"hello"],0))
def SameStuff(l1, l2):
    if l1 and l2:  # both contain something
        try:
            index = l2.index(l1[0])

            return SameStuff(l1[1:], l2[:index] + l2[1 + index:])  # recurse

        except ValueError:

            return False  # a value in one wasn't found in the other

    return not(l1 or l2)  # only one contains something (False), or neither do (True)

Another idea is to insert three more default parameters (those would not be needed for the first function call): an empty dictionary, an integer index, and a boolean. 另一个想法是再插入三个默认参数(第一个函数调用不需要这些默认参数):空字典,整数索引和布尔值。

Use the boolean to indicate which list we are traversing and the index to point to the current list element (we could also just use a sign on the index instead of the boolean). 使用布尔值指示要遍历的列表,并使用索引指向当前列表元素(我们也可以在索引上使用符号而不是布尔值)。 When traversing the first list, record in the dictionary the count of each unique element encountered, using the element as key. 当遍历第一个列表时,使用元素作为键在字典中记录遇到的每个唯一元素的计数。 At the end, flip the boolean and traverse the second list, this time subtracting from the counts of elements in the dictionary. 最后,翻转布尔值并遍历第二个列表,这次从字典中的元素计数中减去。 Remove any elements reaching zero counts. 删除所有达到零计数的元素。 Assuming we've already tested for matching list lengths, if an element is not found in the dictionary, the lists do not match. 假设我们已经测试了匹配列表的长度,如果在字典中找不到元素,则列表不匹配。

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

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