Подсчитайте количество подмассивов таким образом, чтобы каждый элемент в подмассиве появлялся не менее двух раз

#python #list #complexity-theory

#python #Список #теория сложности

Вопрос:

Я столкнулся с проблемой и, похоже, не могу найти эффективного решения. Проблема заключается в следующем:

Учитывая массив A, подсчитайте количество последовательных непрерывных подмассивов таким образом, чтобы каждый элемент в подмассиве появлялся по крайней мере дважды.

Например, для:

 A = [0,0,0]
 

Ответ должен быть 3, потому что у нас есть

 A[0..1] = [0,0]
A[1..2] = [0,0]
A[0..3] = [0,0,0]
 

Другой пример:

 A=[1,2,1,2,3]
 

Ответ должен быть 1, потому что у нас есть:

 A[0..3] = [1,2,1,2]
 

Кажется, я не могу придумать эффективного решения для этого алгоритма. У меня есть алгоритм, который проверяет все возможные подмассивы (O (n ^ 2)), но мне нужно что-то получше. Это мое наивное решение:

 def duplicatesOnSegment(arr):
    total = 0
    for i in range(0,len(arr)):
        unique = 0
        test = {}
        for j in range(i,len(arr)):
            k = arr[j]
            if k not in test:
                test[k] = 1
            else:
                test[k]  =  1

            if test[k] == 1:
                unique  = 1
            elif test[k] == 2:
                unique -= 1
            if unique == 0:
                total  = 1
    return total
 

Ответ №1:

Ваша программа в худшем случае больше O (n ^ 2), поскольку вы используете if k not in test во вложенном цикле. in В худшем случае это O (n), что приводит к общему наихудшему случаю O (n ^ 3). У меня есть это, O (n ^ 2) в худшем случае, решение, которое использует collections.defaultdict как хэш, чтобы ускорить это.

 from collections import defaultdict

def func(A):
    result = 0
    for i in range(0,len(A)):
        counter = 0
        hash = defaultdict (int)
        for j in range (i, len(A)):
            hash[A[j]]  = 1
            if hash[A[j]] == 2:
                counter  = 1
            if counter != 0 and counter == len(hash):
                result  = 1
    return result
 

Комментарии:

1. Объяснение: counter отслеживает, сколько значений в текущем подмассиве появляется как минимум дважды. Если все отдельные элементы появляются дважды, у нас есть допустимый подмассив, следовательно, увеличиваем result

Ответ №2:

Для начала я бы рассмотрел отрицание интересующего свойства :

not(all(x in l appears at least twice)) = exists(x in l such that any other y in l != x)

Пока не уверен, что предыдущая переформулировка вашего вопроса может помочь, но моя интуиция как математика подсказала мне попробовать этот способ… Тем не менее, все равно похоже на O (n ^ 2)…

 my_list = ['b', 'b', 'a', 'd', 'd', 'c']

def remaining_list(el,list):
    assert el in list
    if el == list[-1]: return []
    else: return list[list.index(el) 1:]

def has_duplicate(el, list):
    assert el in list
    return el in remaining_list(el,list)

list(filter(lambda e:not(has_duplicate(e,my_list)),my_list))
 

Комментарии:

1. Насколько я понимаю, это не отвечает на вопрос, поскольку оно просто отфильтровывает все уникальные элементы (что можно было бы сделать за линейное время с помощью hashmaps). В вопросе запрашивается количество смежных подмассивов, которые появляются в массиве