Решить почти повышение уровня (Codefights)
Учитывая последовательность целых чисел в виде массива, определите, можно ли получить строго возрастающую последовательность, удалив из массива не более одного элемента.
Пример
Для последовательности [1, 3, 2, 1]
вывод должен быть:
almostIncreasingSequence(sequence) = false;
В этом массиве нет ни одного элемента, который можно удалить, чтобы получить строго возрастающую последовательность.
Для последовательности [1, 3, 2]
выход должен быть:
almostIncreasingSequence(sequence) = true.
Вы можете удалить 3 из массива, чтобы получить строго возрастающую последовательность [1, 2]. В качестве альтернативы вы можете удалить 2, чтобы получить строго возрастающую последовательность [1, 3].
Мой код:
def almostIncreasingSequence(sequence):
c= 0
for i in range(len(sequence)-1):
if sequence[i]>=sequence[i+1]:
c +=1
return c<1
Но он не может пройти все тесты.
input: [1, 3, 2]
Output:false
Expected Output:true
Input: [10, 1, 2, 3, 4, 5]
Output: false
Expected Output: true
Input: [0, -2, 5, 6]
Output: false
Expected Output: true
input: [1, 1]
Output: false
Expected Output: true
Input: [1, 2, 3, 4, 3, 6]
Output: false
Expected Output: true
Input: [1, 2, 3, 4, 99, 5, 6]
Output: false
Expected Output: true
Ответы
Ответ 1
Ваш алгоритм слишком упрощен. У вас есть правильная идея, проверяющая последовательные пары элементов, что более ранний элемент меньше, чем более поздний элемент, но требуется больше.
Выполните процедуру first_bad_pair(sequence)
, которая проверит список, в котором находятся все пары элементов. Если да, верните значение -1
. В противном случае верните индекс предыдущего элемента: это будет значение от 0
до n-2
. Тогда один алгоритм, который будет работать, - проверить исходный список. Если он работает, отлично, но если не попытаться удалить предыдущие или более поздние элементы-нарушители. Если кто-то из них работает, отлично, в противном случае не очень хорошо.
Я могу думать о других алгоритмах, но это кажется самым простым. Если вам не нравятся временные списки "вверх-вниз", которые создаются путем объединения двух срезов исходного списка, эквивалент может быть выполнен с помощью сравнения в исходном списке с использованием более выражений if
.
Вот код Python, который передает все тесты, которые вы показываете.
def first_bad_pair(sequence):
"""Return the first index of a pair of elements where the earlier
element is not less than the later elements. If no such pair
exists, return -1."""
for i in range(len(sequence)-1):
if sequence[i] >= sequence[i+1]:
return i
return -1
def almostIncreasingSequence(sequence):
"""Return whether it is possible to obtain a strictly increasing
sequence by removing no more than one element from the array."""
j = first_bad_pair(sequence)
if j == -1:
return True # List is increasing
if first_bad_pair(sequence[j-1:j] + sequence[j+1:]) == -1:
return True # Deleting earlier element makes increasing
if first_bad_pair(sequence[j:j+1] + sequence[j+2:]) == -1:
return True # Deleting later element makes increasing
return False # Deleting either does not make increasing
Если вы хотите избежать этих временных списков, вот еще один код, который имеет более сложную процедуру проверки пары.
def first_bad_pair(sequence, k):
"""Return the first index of a pair of elements in sequence[]
for indices k-1, k+1, k+2, k+3, ... where the earlier element is
not less than the later element. If no such pair exists, return -1."""
if 0 < k < len(sequence) - 1:
if sequence[k-1] >= sequence[k+1]:
return k-1
for i in range(k+1, len(sequence)-1):
if sequence[i] >= sequence[i+1]:
return i
return -1
def almostIncreasingSequence(sequence):
"""Return whether it is possible to obtain a strictly increasing
sequence by removing no more than one element from the array."""
j = first_bad_pair(sequence, -1)
if j == -1:
return True # List is increasing
if first_bad_pair(sequence, j) == -1:
return True # Deleting earlier element makes increasing
if first_bad_pair(sequence, j+1) == -1:
return True # Deleting later element makes increasing
return False # Deleting either does not make increasing
И вот те тесты, которые я использовал.
print('\nThese should be True.')
print(almostIncreasingSequence([]))
print(almostIncreasingSequence([1]))
print(almostIncreasingSequence([1, 2]))
print(almostIncreasingSequence([1, 2, 3]))
print(almostIncreasingSequence([1, 3, 2]))
print(almostIncreasingSequence([10, 1, 2, 3, 4, 5]))
print(almostIncreasingSequence([0, -2, 5, 6]))
print(almostIncreasingSequence([1, 1]))
print(almostIncreasingSequence([1, 2, 3, 4, 3, 6]))
print(almostIncreasingSequence([1, 2, 3, 4, 99, 5, 6]))
print(almostIncreasingSequence([1, 2, 2, 3]))
print('\nThese should be False.')
print(almostIncreasingSequence([1, 3, 2, 1]))
print(almostIncreasingSequence([3, 2, 1]))
print(almostIncreasingSequence([1, 1, 1]))
Ответ 2
Это мое. Надеемся, что вы сочтете это полезным:
def almostIncreasingSequence(sequence):
#Take out the edge cases
if len(sequence) <= 2:
return True
#Set up a new function to see if it increasing sequence
def IncreasingSequence(test_sequence):
if len(test_sequence) == 2:
if test_sequence[0] < test_sequence[1]:
return True
else:
for i in range(0, len(test_sequence)-1):
if test_sequence[i] >= test_sequence[i+1]:
return False
else:
pass
return True
for i in range (0, len(sequence) - 1):
if sequence[i] >= sequence [i+1]:
#Either remove the current one or the next one
test_seq1 = sequence[:i] + sequence[i+1:]
test_seq2 = sequence[:i+1] + sequence[i+2:]
if IncreasingSequence(test_seq1) == True:
return True
elif IncreasingSequence(test_seq2) == True:
return True
else:
return False
Ответ 3
Причина, по которой ваш скромный алгоритм не работает здесь (кроме отсутствующего '=' взамен), заключается в том, что он просто считает элементы, которые больше, чем следующий, и возвращает результат, если это число больше 1.
В этом случае важно посмотреть на список после удаления из него по одному элементу за раз и убедиться, что это все еще отсортированный список.
Моя попытка этого очень коротка и работает для всех сценариев. Он не соответствует временному ограничению последнего скрытого теста, заданного в упражнении в одиночку.
![enter image description here]()
Как следует из названия проблемы, я непосредственно хотел сравнить список с его отсортированной версией и позже обработать "почти" случай - таким образом, имея почти IncreasingSequence. т.е.:
if sequence==sorted(sequence):
.
.
Но, как говорит проблема:
определить, можно ли получить строго возрастающую последовательность, удаляя не более одного элемента из массива (за раз).
Я начал визуализировать список, удаляя элемент за раз во время итерации и проверяя, является ли остальная часть списка отсортированной версией. Таким образом, подводит меня к этому:
for i in range(len(sequence)):
temp=sequence.copy()
del temp[i]
if temp==sorted(temp):
.
.
Именно здесь я смог увидеть, что если это условие верно для полного списка, то у нас есть то, что требуется - почти IncreasingSequence! Итак, я завершил свой код следующим образом:
def almostIncreasingSequence(sequence):
t=0
for i in range(len(sequence)):
temp=sequence.copy()
del temp[i]
if temp==sorted(temp):
t+=1
return(True if t>0 else False)
Это решение все еще не работает в таких списках, как [1, 1, 1, 2, 3].
Как отметил @rory-daulton в своих комментариях, мы должны различать "отсортированную" и "возрастающую последовательность" в этой задаче. В то время как тест [1, 1, 1, 2, 3] отсортирован, он имеет возрастающую последовательность, как того требует проблема. Для этого ниже приведен окончательный код с добавлением условия в одну строку для проверки последовательных одинаковых номеров:
def almostIncreasingSequence(sequence):
t=0
for i in range(len(sequence)):
temp=sequence.copy()
del temp[i]
if temp==sorted(temp) and not(any(i==j for i,j in zip(sorted(temp), sorted(temp)[1:]))):
t+=1
return t>0
Так как это все еще не соответствует времени выполнения последнего теста (список должен быть очень большим), я все еще ищу, есть ли способ оптимизировать это мое решение.
Ответ 4
Я все еще работаю над собой. Написал это так, но я не могу пройти последние 3 скрытых теста.
def almostIncreasingSequence(sequence):
boolMe = 0
checkRep = 0
for x in range(0, len(sequence)-1):
if sequence[x]>sequence[x+1]:
boolMe = boolMe + 1
if (x!=0) & (x!=(len(sequence)-2)):
if sequence[x-1]>sequence[x+2]:
boolMe = boolMe + 1
if sequence.count(sequence[x])>1:
checkRep = checkRep + 1
if (boolMe > 1) | (checkRep > 2):
return False
return True
Ответ 5
Это было довольно крутое упражнение.
Я сделал это вот так:
def almostIncreasingSequence(list):
removedIdx = [] #Indexes that need to be removed
for idx, item in enumerate(list):
tmp = [] #Indexes between current index and 0 that break the increasing order
for i in range(idx-1, -1, -1):
if list[idx]<=list[i]: #Add index to tmp if number breaks order
tmp.append(i)
if len(tmp)>1: #If more than one of the former numbers breaks order
removedIdx.append(idx) #Add current index to removedIdx
else:
if len(tmp)>0: #If only one of the former numbers breaks order
removedIdx.append(tmp[0]) #Add it to removedIdx
return len(set(removedIdx))<=1
print('\nThese should be True.')
print(almostIncreasingSequence([]))
print(almostIncreasingSequence([1]))
print(almostIncreasingSequence([1, 2]))
print(almostIncreasingSequence([1, 2, 3]))
print(almostIncreasingSequence([1, 3, 2]))
print(almostIncreasingSequence([10, 1, 2, 3, 4, 5]))
print(almostIncreasingSequence([0, -2, 5, 6]))
print(almostIncreasingSequence([1, 1]))
print(almostIncreasingSequence([1, 2, 3, 4, 3, 6]))
print(almostIncreasingSequence([1, 2, 3, 4, 99, 5, 6]))
print(almostIncreasingSequence([1, 2, 2, 3]))
print('\nThese should be False.')
print(almostIncreasingSequence([1, 3, 2, 1]))
print(almostIncreasingSequence([3, 2, 1]))
print(almostIncreasingSequence([1, 1, 1]))
print(almostIncreasingSequence([1, 1, 1, 2, 3]))
Ответ 6
С Python3 я начал с чего-то вроде этого...
def almostIncreasingSequence(sequence):
for i, x in enumerate(sequence):
ret = False
s = sequence[:i]+sequence[i+1:]
for j, y in enumerate(s[1:]):
if s[j+1] <= s[j]:
ret = True
break
if ret:
break
if not ret:
return True
return False
Но продолжался тайм-аут на чеке # 29.
Я пнул себя, когда понял, что это тоже работает, но все же время от времени на # 29. Я не знаю, как ускорить его.
def almostIncreasingSequence(sequence):
for i, x in enumerate(sequence):
s = sequence[:i]
s.extend(sequence[i+1:])
if s == sorted(set(s)):
return True
return False
Ответ 7
Вот мое простое решение
def almostIncreasingSequence(sequence):
removed_one = False
prev_maxval = None
maxval = None
for s in sequence:
if not maxval or s > maxval:
prev_maxval = maxval
maxval = s
elif not prev_maxval or s > prev_maxval:
if removed_one:
return False
removed_one = True
maxval = s
else:
if removed_one:
return False
removed_one = True
return True
Ответ 8
Ну, вот и мое решение,
Я думаю, что это немного чище, чем другие решения, предложенные здесь, поэтому я просто приведу его ниже.
Он в основном проверяет индекс, в котором значение i -th больше значения (i + 1) -th, если он находит такой индекс, проверяет, превращает ли какой-либо из этих двух список в увеличивающийся последовательность.
def almostIncreasingSequence(sequence):
def is_increasing(lst):
for idx in range(len(lst)-1):
if lst[idx] >= lst[idx + 1]:
return False
return True
for idx in range(len(sequence) - 1):
if sequence[idx] >= sequence[idx + 1]:
fixable = is_increasing([*sequence[:idx], *sequence[idx+1:]]) or is_increasing([*sequence[:idx+1], *sequence[idx+2:]])
if not fixable:
return False
return True
Ответ 9
boolean almostIncreasingSequence(int[] sequence) {
int length = sequence.length;
if(length ==1) return true;
if(length ==2 && sequence[1] > sequence[0]) return true;
int count = 0;
int index = 0;
boolean iter = true;
while(iter){
index = checkSequence(sequence,index);
if(index != -1){
count++;
index++;
if(index >= length-1){
iter=false;
}else if(index-1 !=0){
if(sequence[index-1] <= sequence[index]){
iter=false;
count++;
}else if(((sequence[index] <= sequence[index-2])) && ((sequence[index+1] <= sequence[index-1]))){
iter=false;
count++;
}
}
}else{
iter = false;
}
}
if(count > 1) return false;
return true;
}
int checkSequence(int[] sequence, int index){
for(; index < sequence.length-1; index++){
if(sequence[index+1] <= sequence[index]){
return index;
}
}
return -1;
}
Ответ 10
Ниже приведен код Python3, который я использовал, и он работал нормально:
def almostIncreasingSequence(sequence):
flag = False
if(len(sequence) < 3):
return True
if(sequence == sorted(sequence)):
if(len(sequence)==len(set(sequence))):
return True
bigFlag = True
for i in range(len(sequence)):
if(bigFlag and i < len(sequence)-1 and sequence[i] < sequence[i+1]):
bigFlag = True
continue
tempSeq = sequence[:i] + sequence[i+1:]
if(tempSeq == sorted(tempSeq)):
if(len(tempSeq)==len(set(tempSeq))):
flag = True
break
bigFlag = False
return flag
Ответ 11
Это работает в большинстве случаев, за исключением проблем с производительностью.
def almostIncreasingSequence(sequence):
if len(sequence)==2:
return sequence==sorted(list(sequence))
else:
for i in range(0,len(sequence)):
newsequence=sequence[:i]+sequence[i+1:]
if (newsequence==sorted(list(newsequence))) and len(newsequence)==len(set(newsequence)):
return True
break
else:
result=False
return result
Ответ 12
Это мое решение,
def nearIncreasingSequence (sequence):
def hasIncreasingOrder(slicedSquence, lengthOfArray):
count =0
output = True
while(count < (lengthOfArray-1)) :
if slicedSquence[count] >= slicedSquence[count+1] :
output = False
break
count = count +1
return output
count = 0
seqOutput = False
lengthOfArray = len(sequence)
while count < lengthOfArray:
newArray = sequence[:count] + sequence[count+1:]
if hasIncreasingOrder(newArray, lengthOfArray-1):
seqOutput = True
break
count = count+1
return seqOutput