Reputation: 351
Question:
"Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
Note: sequence a0, a1, ..., an is considered to be a strictly increasing if a0 < a1 < ... < an. Sequence containing only one element is also considered to be strictly increasing.
Examples:
For sequence = [1, 3, 2, 1], the output should be solution(sequence) = false. There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2], the output should be solution(sequence) = true. You can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, you can remove 2 to get the strictly increasing sequence [1, 3]."
Here's my code:
def solution(sequence):
if len(sequence) == 1:
return True
else:
count = 0
for i in range(0,len(sequence) - 1):
if sequence[i] >= sequence[i + 1]:
count = count + 1
for i in range(0,len(sequence) - 2):
if sequence[i] >= sequence[i + 2]:
count = count + 1
return count <= 1
My code covers three cases:
Case 1: when the sequence is just one element long. I caught that in the first if statement.
Case 2: If there's more than one down-step – a case where the neighbour is less than the element being considered – then there is no way to adjust the sequence with just one removal, and so we get false (count > 1). I caught this in the first if statement.
Case 3: There are some cases, however, where there is only one down-step but there is still no way to remove just one element. This happens when the second element along is also less than the element being considered. For example, with [1,4,3,2] even if you removed the 3, you would still get a downstep. Now I covered this case by doing a second check, which checked whether the element two along is less, and if it is, then we add to the count.
Case 4: There is a case my code doesn't cover, which seems to be the only one, and that is when an element's neighbour and the next element along are both smaller than the element under consideration, but we could solve the issue just by getting rid of the element under consideration. So, with [1,4,2,3] both 2 and 3 are smaller than 4, but if we just got rid of the 4, then we're good. This case can occur either when the problem element is the first in the sequence or not. I'm not sure how to capture this properly. I suppose you might add in a conditional which looked at whether i-2 is less than i+1, but this won't work when i indexes the first element and it's quite cumbersome. I'm not sure how to go sort this out.
I'm quite sure I've overcomplicated things and what really is needed is to step back and think of a less piece-meal solution, but I'm stuck. Could anyone help? Note that we don't have to actually obtain the strictly increasing sequence; we just have to see whether we could.
Upvotes: 1
Views: 2729
Reputation: 1
def solution(sequence):
boolean_list = []
setted = set(sequence)
#this if checks for 2 or more duplicated numbers
if (len(sequence) - len(setted)) >= 2:
return False
else:
#this for loop runs for every i item in sequence list
for i in sequence:
test = []
#this for loop creates a test list without i item
for j in sequence:
if j != i:
test.append(j)
# this variable checks if all the items in the test list are in ascending order
is_ascending = all(test[x] <= test[x+1] for x in range(len(test)-1))
# this is a list of boolean values with the result of every case
boolean_list.append(is_ascending)
# this returns True if at least one case is True else it returns False
return any(boolean_list)
Upvotes: 0
Reputation: 11
Try this
def solution(sequence):
n = len(sequence)
for i in range(n):
count = 0
trail = sequence[:]
del trail[i]
m = len(trail)
for j in range(m-1):
if trail[j] >= trail[j+1]:
count += 1
if count == 0:
return True
return False
This is not efficient nor optimized but it does the work.
Upvotes: 1
Reputation: 11347
Let's split the input into at most two increasing subsequences. If this is not possible, return false.
If there's only one sequence, return true.
If the length of either sequence is 1, the answer is true - we simply remove this element.
Otherwise we can join two sequences by either removing the last item from the first sequence, or the first item of the second one. That is,
if a[j-2] < a[j] -> ok, remove a[j - 1]
if a[j-1] < a[j + 1] -> ok, remove a[j]
where j
is the index where the second sequence starts.
Code:
def check(a):
j = 0
for i in range(1, len(a)):
if a[i - 1] >= a[i]:
if j > 0:
return None
j = i
if j == 0:
return a
if j == 1:
return a[1:]
if j == len(a) - 1:
return a[:-1]
if a[j - 2] < a[j]:
return a[:(j - 1)] + a[j:]
if a[j - 1] < a[j + 1]:
return a[:j] + a[(j + 1):]
return None
assert check([2, 4, 6, 8]) == [2, 4, 6, 8], 'j == 0'
assert check([9, 4, 6, 8]) == [4, 6, 8], 'j == 1'
assert check([4, 6, 8, 1]) == [4, 6, 8], 'j == len-1'
assert check([2, 4, 9, 6, 8]) == [2, 4, 6, 8], 'j-2 < j'
assert check([2, 4, 1, 6, 8]) == [2, 4, 6, 8], 'j-1 < j+1'
assert check([2, 2, 2, 2]) is None, 'early return'
assert check([2, 8, 9, 6, 1]) is None, 'early return'
assert check([2, 4, 9, 3, 5]) is None, 'last return'
assert check([2]) == [2]
Upvotes: 1
Reputation: 7152
Here is an idea you can a look at (edited after comments)
def distinct(L: list[int]) -> bool:
return len(L) == len(set(L))
def almost_increasing(L: list[int]) -> bool:
# some trivial cases
if len(L) <= 2: return True
if L[1: ] == sorted(L[1: ]) and distinct(L[1: ]): return True
if L[:-1] == sorted(L[:-1]) and distinct(L[:-1]): return True
return any(
L[ :i] == sorted(L[ :i]) and distinct(L[ :i]) and
L[i+1:] == sorted(L[i+1:]) and distinct(L[i+1:]) and
L[i-1 ] < L[i+1]
for i in range(1, len(L)-1)
)
And here is a nice way you can test it with hypothesis and pytest:
@given(L=st.lists(st.integers(), min_size=2, max_size=6))
def test_almost_increasing(L: list[int]):
expected = False
for i in range(len(L)):
Lcopy = L.copy()
del Lcopy[i]
expected |= (Lcopy == sorted(Lcopy) and distinct(Lcopy))
received = almost_increasing(L)
assert received == expected
Upvotes: 1
Reputation: 483
def solution(sequence):
"""determine strict increase"""
sequence_length = len(sequence)
if (
sequence_length == 0
or not len(set(sequence)) + 1 >= sequence_length
):
return False
return True
Upvotes: -1
Reputation: 183
Try this:
def is_solution(list_to_check):
if len(list_to_check) == 1:
return True
for i in range(1, len(list_to_check)):
if list_to_check[i] <= list_to_check[i - 1]:
new_list = list_to_check[:i - 1] + list_to_check[i:]
if (list_to_check[i] > list_to_check[i - 2]
and new_list == sorted(new_list)):
return True
elif (i == len(list_to_check) - 1
and list_to_check[:-1] == sorted(list_to_check[:-1])):
return True
return False
if __name__ == '__main__':
list_to_check = [1, 2, 1]
print(is_solution(list_to_check))
Upvotes: 0