代码的目标是查看序列是否几乎增加,也就是说,可以通过删除单个元素来严格增加序列。
例如:如果索引1处的元素被删除,[1, 3, 2, 3]
将严格增加。 [1, 2, 1, 2]
几乎没有增加,因为如果您删除了第一个' 2',那么[1, 1, 2]
就不会严格增加。
对于长度为2 <= len <= 10^5
的序列,我的代码必须在4000毫秒以下工作。它可能会被很长的序列所吸引。
以下是代码:
def almostIncreasingSequence(sequence):
for i in range(len(sequence)):
c = sequence.pop(i)
if sequence == sorted(sequence):
for item in sequence:
if sequence.count(item) != 1:
break
else:
return True
sequence.insert(i, c)
return False
答案 0 :(得分:1)
你的“几乎增加”的条件可以用以下两条规则来改写:
i
不满足ai < ai+1
。ai < ai+2
。这是一个可以在O(n)
时间内轻松评估的问题:
def almostIncreasingSequence(sequence):
iterator = iter(enumerate(sequence))
prev = next(iterator)
found = False
for item in iterator:
if item[1] <= prev[1]:
if found:
return False
if prev[0] > 0 and item[0] < len(sequence) - 1 \
and sequence[prev[0] - 1] >= item[1]:
return False
found = True
prev = item
return True
如果你被允许使用numpy:
def almostIncreasingSequence(sequence):
ind = np.where(np.diff(sequence) <= 0)[0]
if len(ind) > 1:
return False
if len(ind) == 1 and (ind[0] == 0 or ind[0] == len(sequence) - 2):
return True
if len(ind) == 0:
return True
return sequence[ind[0] + 1] > sequence[ind[0] - 1]
选择树是为了清楚起见。它可以重写为单个return语句:
return len(ind) == 0 or \
(len(ind) == 1 and (ind[0] == 0 or \
ind[0] == len(sequence) - 1 or \
sequence[ind[0] - 1] < sequence[ind[0] + 1]))
这两种解决方案都能对[6, 5, 6, 7]
和[1, 2, 3, 1]
等边缘情况做出正确反应。
答案 1 :(得分:0)
计算sequence
中相邻元素的差异,并找出它不会增加的频率(即差异不是正的频率):
def almost_increasing(seq):
if type(seq)==type([]):
seq = np.array(seq)
diff = seq[1:] - seq[:-1] # differences of neighboring elements
indices = np.where(diff <= 0)[0]
if len(indices) == 0: return True # increasing sequence, case 1
elif len(indices) == 1 and indices[0] == len(seq) - 2: return True # non-increase only at last element, case 2
elif len(indices) == 1 and indices[0] == len(seq) - 1 and seq[-3] < seq[-1]: return True # non-increase only at forelast element, case 3
elif len(indices) == 1 and seq[indices[0]-1] < seq[indices[0]+1]: return True # case 4
elif len(indices) == 1 and seq[indices[0]] < seq[indices[0]+2]: return True # case 5
else: return False
# For understanding, maybe insert print(indices)
print(almost_increasing([1,2,3])) # case 1
print(almost_increasing([1,2,3,4,1])) # case 2
print(almost_increasing([1,2,3,1,4])) # case 3
print(almost_increasing([1,3,2,3])) # case 4
print(almost_increasing([1,2,1,4])) # case 5
print(almost_increasing([1,2,1,2]))
# performance
import time
start = time.clock()
almost_increasing(np.random.random(100000))
stop = time.clock()
print(stop-start)
案例4和5的不同之处在于从序列中删除的元素的选择。
答案 2 :(得分:-1)
如果你提供一些测试会很棒:但是我尝试了一些优势,当大小超过3时,重要的是要关注连续性。只需要区分列表并确保n-3是1。希望我没有误会
import itertools
import numpy as np
def ais(sequence):
if len(sequence) < 3: # trivial cases for length 1 and 2
return True
if len(sequence)==3: # can afford a lazy look
for perm in itertools.permutations(sequence):
if perm[1:][1]-perm[1:][0] == 1:
return True
return False
else:
return list(np.diff(sequence)).count(1) == (len(sequence)-3)