Часть кода for i in range(len(arr))
может быть упрощена, но я считаю, что это не проблема, вызывающая чрезмерное время выполнения.
Вам следует избегать просмотра списка с самого начала на каждой итерации. Когда вы найдете свой первый «несортированный» индекс, вы должны следить за ним, чтобы при следующем проходе вы начинали процесс оттуда, а не каждый раз с нуля индекса. Это должно сократить ненужные циклы по мере постепенной сортировки массива.
Во-вторых, в заявлении о проблеме не требуется увеличивать порядок индексов, поэтому вы можете выбрать любые 3 индекса в списке. Лучшей стратегией было бы выбрать 3 индекса так, чтобы операция сдвига помещала как минимум два значения в их соответствующую позицию:
- i1 должна быть первой несортированной позицией
- i2 должен быть индексом, где находится соответствующее значение i1. Он будет иметь индекс> i1, поскольку i1 - это первая несортированная позиция
- i3 должен быть индексом, где находится соответствующее значение i2. это немного сложнее, потому что вы, возможно, прошли эту позицию, когда достигнете желаемого индекса для i2. Таким образом, есть две возможности:
- a) значение для i2 находится дальше, чем i2: просто используйте его, когда найдете его
- b) значение для i2 было до i2: используйте последнее Индекс, который вы нашли между i1 и i2, и позвольте этому разрешиться на следующем проходе
.
def shift3(K,p):
lasti = 0
for _ in range(K):
i1 = i2 = i3 = None
for i in range(lasti,len(p)):
print(i,i1,i2,i3)
if p[i] == i+1: # find next unsorted position
continue
if i1 is None: # use first unsorted position as i1
lasti = i1 = i # also record highest sorted position
continue
if p[i] == i1+1: # i2 is position of element that should be at i1
i2 = i
if i3 is None or p[i] == i2+1: # i3 is position of i2 element (if possible)
i3 = i
if i2 is not None and i3 is not None: # perform shift
p[i1],p[i2],p[i3] = p[i2],p[i3],p[i1]
break
x = [1,7,3,2,4,6,5]
shift3(5,x)
print(x)
# [1, 2, 3, 4, 5, 6, 7]