Программа, которую я пытался выполнить, имеет следующую формулировку проблемы:

Программа должна принимать N целых чисел, содержащих целые числа от 1 до N с дубликатами в любом порядке. Программа должна вывести отсутствующие целые числа от 1 до N среди заданных целых чисел в порядке возрастания в качестве выходных данных.

Пример :

Вход: 5

2 5 5 1 1

Выход: 3 4

Пояснение: целые числа 3 и 4 отсутствуют в 5 целых числах 2 5 5 1 1. Следовательно, 3 и 4 выводятся как выходные данные.

Мой код:

def modusoperandi(n, t):
    if str(n) not in t:
        yield n 

n = int(input())
t = tuple(sr for sr in input().split())
for i in range(1,n+1):
    for j in modusoperandi(i,t):
        print(j,end=' ')

Мой код, однако, не прошел все тестовые случаи, поскольку для тестовых случаев с огромным вводом требуется значительное количество времени [требуется более 500 мс, что является временным ограничением].

Я пытался вычислить время выполнения, используя метод timeit . Странно, что когда число элементов в кортеже увеличивается, время выполнения также увеличивается для данного N. Я предпочел кортеж над списком, поскольку он должен быть более эффективным.

1
Ganesh 1 Июл 2019 в 17:18

4 ответа

Лучший ответ

Вы захотите преобразовать существующие числа в выражения int, а затем поместить их в set; Наборы очень эффективны для выяснения, является ли данное значение членом.

n = int(input())
extant = set(int(n) for n in input().split())
for i in range(1, n + 1):
    if i not in extant:
        print(i, end=" ")
5
AKX 1 Июл 2019 в 14:22

Вы должны подумать о сложности вашего решения (что довольно плохо):

def modusoperandi(n, t):
    # Since 't' is a tuple, the complexity of 'not in t' is O(len(t))
    # This makes the overall complexity of this function O(len(t))
    if str(n) not in t:
        yield n 

n = int(input())
t = tuple(sr for sr in input().split()) # O(len(t))
for i in range(1,n+1):  # O(n) iterations

    # 0 or 1 iteration, but the call to 'modusoperandi' is O(len(t))
    for j in modusoperandi(i,t):  
        print(j,end=' ')

Общая сложность O (n * len (t)). Это не очень хорошая сложность. Вы хотели бы иметь сложность, которая является линейной на входе. Есть два способа:

  1. Используйте хеш-таблицу, чтобы отметить все посещенные целые числа, и set такая хеш-таблица. К сожалению, хеш-таблицы имеют некоторые недостатки.
  2. Поскольку существует n записей и числа находятся в диапазоне 1..n, тогда очень эффективно использовать характеристический вектор values_encountered, в котором values_encountered[i] равен True тогда и только тогда, когда встречается значение i. При таком большом вводе это решение, вероятно, будет работать быстрее, чем набор, и потреблять меньше памяти.

.

import numpy as np
n = int(input())

values_encountered = np.zeros(n+1, dtype=bool)     # O(n)
values_encountered[[int(i) for i in input().split()]] = True # O(n)
# Or:
# values_encountered[list(map(int, input().split()))] = True

values_missing= (values_encountered == False) # O(n)
values_missing[0] = False
print(*list(*values_missing.nonzero())) # O(n)
0
Michael Veksler 1 Июл 2019 в 15:28

Ключ действительно должен использовать набор для проверки наличия ожидаемых чисел во входной строке. Вам не нужно преобразовывать входные данные в целые числа. Вы можете сделать это наоборот, генерируя последовательные числа в виде строк.

nums    = input().split()
numSet  = set(nums)
missing = " ".join(str(n) for n in range(1,len(nums)+1) if str(n) not in numSet)

print(missing) # 3 4

Для этой конкретной проблемы есть несколько более быстрая альтернатива использованию набора, потому что вы можете позволить себе создать массив флагов с известным (и разумным) размером:

numbers = input().split()
present = [False]*len(numbers)
for n in numbers: present[int(n)-1] = True
missing = " ".join(str(n+1) for n,seen in enumerate(present) if not seen)
1
Alain T. 1 Июл 2019 в 15:29
n = '5'
i = '2 5 5 1 1'

def compute(n, i):
    s1 = set(range(1, n+1))
    yield from sorted(s1.difference(i))


for val in compute(int(n), map(int, i.split()) ):
    print(val, end=' ')

Печать :

3 4 
0
Andrej Kesely 1 Июл 2019 в 14:24