假设您的数字都是非负数,您可以使用更有效的算法。您只需在列表中运行两个指针 ptrA 和 ptrB,保持包含元素的总和。
如果总和不是你需要的,你做两件事之一。首先,如果您当前的总和小于所需的总和,则通过推进ptrB 将下一个元素带入数组。
如果您当前的总和比您需要的多更多,您可以通过推进ptrA 取出范围中的第一个元素。当然,这两个操作都应该调整当前范围和。这里有一个极端情况,如果当前范围内只有一个项目,您不想这样做。
不用说,如果当前范围总和等于您需要的,您只需删除该范围并退出。
就伪代码而言,它是这样的:
def delExact(list, desiredSum):
# Check non-empty and start range.
if list is empty:
return
ptrA = list.first
ptrB = ptrA
rangeSum = ptrA.value
# Continue until match found
while rangeSum is not equal to desiredSum:
# Select add-another or remove-first.
if ptrA == ptrB, or rangeSum < desiredSum:
# Need to bring another in, returning if list exhausted.
ptrB = ptrB.next
if ptrB == null:
return
rangeSum = rangeSum + ptrB.value
else:
# Need to remove one.
rangeSum = rangeSum - ptrA.value
ptrA = ptrA.next
# If we exit the loop, we've found a sum match.
# Hence we need to delete ptrA through ptrB inclusive.
但是,如果允许负数,这种两指针方法就会失效,因为您实际上并不知道后面的元素可能会产生什么影响。
在这种情况下,您基本上必须对所有可能性进行详尽的搜索,这基本上可以归结为:
for each element in list:
for each possible segment from that element on:
check and act on summed data
这实际上更像是一种英文表示,这种野兽的伪代码如下:
def delExact(list, desiredSum):
# For each list element.
ptrA = list.first
while ptrA is not null:
# For each possible segment starting at that element.
segmentSum = 0
ptrB = ptrA
while ptrB is not null:
add ptrB.value to segmentSum
# Delete segment if sum matches, then return.
if segmentSum is equal to desiredSum:
# Here we delete from ptrA through ptrB inclusive.
return
# Otherwise, keep adding elements to segment.
ptrB = ptrB.next
# No matching segment, move on to next element.
ptrA = ptrA.next
# No matching segment at any element, just return.
使用这些算法中的任一种将解决您关于仅删除两个元素的问题。
在列表开头删除的问题是简单地认识到这一事实(ptrA == list.first)并确保在这种情况下调整first 指针。这是链表处理中的标准边缘情况,可以实现为:
def deleteRangeInclusive(list, ptrA, ptrB):
# Adjust list to remove ptrA/ptrB segment,
# allowing for possibility ptrA may be the head.
if ptrA == list.first:
list.first = ptrB.next
else:
beforeA = list.first
while beforeA.next != ptrA:
beforeA = beforeA.next
beforeA.next = ptrB.next
# Now we can safely remove the ptrA-ptrB segment.
while ptrA != ptrB:
tempA = ptrA
ptrA = ptrA.next
delete element tempA
delete element ptrB