Algorithm Search⌘K

Proofs: Histogram stack algorithm

These are the human proofs of Histogram stack algorithm, at full length.

The histogram stack algorithm returns the largest rectangle full

This proof shows: correctness.

We use the pseudocode of the page on heights h[0..n−1]≥0h[0..n-1] \ge 0, and we set h[n]=0h[n] = 0, the value that line L3 uses at i=ni = n. For 0≤a≤b≤n−10 \le a \le b \le n - 1 let area(a,b)=(b−a+1)min⁡a≤l≤bh[l]\text{area}(a, b) = (b - a + 1) \min_{a \le l \le b} h[l], and let A∗A^* be the largest such area, or 00 if n=0n = 0. Write the stack from the bottom as S=[s1,…,st]S = [s_1, \dots, s_t] and set s0=−1s_0 = -1.

Lemma 1 (invariants). At the start of each step ii (0≤i≤n0 \le i \le n):

  1. s1<⋯<st≤i−1s_1 < \dots < s_t \le i - 1 and h[s1]<⋯<h[st]h[s_1] < \dots < h[s_t];
  2. for 1≤q≤t1 \le q \le t, every ll with sq−1<l<sqs_{q-1} < l < s_q has h[l]≥h[sq]h[l] \ge h[s_q];
  3. if i≥1i \ge 1, then t≥1t \ge 1 and st=i−1s_t = i - 1.

Proof. At i=0i = 0 the stack is empty. Suppose the lemma holds at the start of step i≤ni \le n and look at the stack just before line L8 of that step, [s1,…,su][s_1, \dots, s_u] with u≤tu \le t. The pops removed exactly su+1,…,sts_{u+1}, \dots, s_t, and they all have h≥x=h[i]h \ge x = h[i], while h[su]<h[i]h[s_u] < h[i] if u≥1u \ge 1, since the loop stopped. Line L8 pushes ii. Part 1 holds for the new stack, since h[su]<h[i]h[s_u] < h[i]. For part 2 with the new top ii, the bars ll with su<l<is_u < l < i are the popped su+1,…,sts_{u+1}, \dots, s_t, each with h≥h[i]h \ge h[i], and the bars between them, each at least as high as the popped bar above it by part 2; so all have h[l]≥h[i]h[l] \ge h[i]. The other parts of part 2 do not change. Part 3 holds since ii is on top. ■\blacksquare

Lemma 2 (each recorded area is real). When line L7 runs for kk at step ii with leftleft from line L6, every bar ll with left<l<ileft < l < i has h[l]≥h[k]h[l] \ge h[k]. So h[k](i−left−1)=area(left+1,i−1)h[k] (i - left - 1) = \text{area}(left + 1, i - 1) if i≤ni \le n, and left+1≤k≤i−1left + 1 \le k \le i - 1.

Proof. At the pop, k=sqk = s_q and left=sq−1left = s_{q-1} for the stack at that moment, which is a prefix of the stack at the start of step ii, so Lemma 1 applies to it. Bars with left<l<kleft < l < k have h[l]≥h[k]h[l] \ge h[k] by part 2. Bars with k<l<ik < l < i are the stack items above kk at the start of the step, which are higher than h[k]h[k] by part 1, and the bars between them, which are at least as high as some such item by part 2, with the last item st=i−1s_t = i - 1 by part 3. The lowest bar of left+1..i−1left + 1..i - 1 is then kk itself. ■\blacksquare

Lemma 3 (when a bar is popped). Bar k≤n−1k \le n - 1 is popped at step iki_k, the least ii with k<i≤nk < i \le n and h[i]≤h[k]h[i] \le h[k], and at that moment left=Lkleft = L_k, the largest l<kl < k with h[l]<h[k]h[l] < h[k], or −1-1.

Proof. Bar kk is pushed at step kk. At a later step ii with h[i]>h[k]h[i] > h[k], the pops stop at kk or above it, because every item above kk is higher than h[k]h[k] and the loop stops at the first item lower than h[i]h[i]; so kk stays. At the first step ii with h[i]≤h[k]h[i] \le h[k], every item above kk is higher than h[k]≥h[i]h[k] \ge h[i], so all of them and then kk are popped. Now left=sq−1left = s_{q-1} has h[left]<h[k]h[left] < h[k] by part 1, and every bar between leftleft and kk has h≥h[k]h \ge h[k] by part 2, so left=Lkleft = L_k. ■\blacksquare

At i=ni = n the value x=0≤h[k]x = 0 \le h[k] for every kk, so ik≤ni_k \le n always exists.

Theorem. LARGEST-RECTANGLE returns A∗A^*.

Proof. By Lemma 2, every value that line L7 compares is the area of a real rectangle, so best≤A∗best \le A^*; and best≥0=A∗best \ge 0 = A^* if n=0n = 0. Let n≥1n \ge 1, and let area(a,b)=A∗\text{area}(a, b) = A^*. Let kk be the largest index in a..ba..b with h[k]=min⁡a≤l≤bh[l]h[k] = \min_{a \le l \le b} h[l]. Bars k+1..bk + 1..b are higher than h[k]h[k], so ik>bi_k > b by Lemma 3. Bars a..k−1a..k-1 are at least h[k]h[k], so Lk<aL_k < a. Line L7 for kk records h[k](ik−Lk−1)≥h[k](b−a+1)=A∗h[k](i_k - L_k - 1) \ge h[k](b - a + 1) = A^*. So best≥A∗best \ge A^* at the end.

Cost. Each of the indices 0..n0..n is pushed once and popped at most once, so the loop of line L4 runs at most n+1n + 1 times in all, and the algorithm stops after Θ(n)\Theta(n) steps. ■\blacksquare

Back to Histogram stack algorithm