Ignore zero adjacent differences. A segment is bitonic in the question's peak-or-valley sense precisely when its remaining difference signs change at most once. Keep the earliest starts of the current monotone suffix and current bitonic suffix:
if n == 0: return (0,0)
monoStart = 0; bitStart = 0
lastDir = 0; lastStrictEnd = 0
best = 1; bestStart = 0
for i = 1,...,n-1:
dir = compare(a[i],a[i-1]) // -1, 0, or +1
if dir != 0:
if lastDir != 0 and dir != lastDir:
bitStart = monoStart
monoStart = lastStrictEnd
lastDir = dir
lastStrictEnd = i
length = i-bitStart+1
if length > best:
best = length; bestStart = bitStart
return (bestStart,best)After processing ,
lastDir is the most recent nonzero difference sign; lastStrictEnd is its endpoint. monoStart is the earliest start of a suffix with only that nonzero direction, and bitStart is the earliest start of a suffix with at most one sign change. The best recorded interval realizes the largest such length over the whole scanned prefix.A zero difference changes neither direction. On reversal, a valid new bitonic suffix may retain the entire old monotone suffix, but cannot retain a preceding opposite-direction run as well, which would create two changes. Hence its earliest start is the old
monoStart. The new monotone suffix starts at lastStrictEnd, retaining the intervening plateau. This proves the update and explains why merely starting at loses valid overlapping segments. The longest bitonic contiguous segment algorithm uses time and auxiliary space; the sample's maximum length is 5.