I usually implement sliding window as:

// [l, r)int l = r = 0;while (r < n) { assert(l <= r); if (extend_window) { r++; } else {    l--; //contract window }}

However, there are cases where we have complicated invariants on the sliding window, such as a maximum length. An example is codeforces 676c , where we must maintain a sliding window which contains at most k >= 0 "illegal" elements.

My flawed implementation using a while loop was:

int best = 0;for(int c = 'a'; c <= 'b'; ++c) {    // window: [l, r)    int l = 0, r = 0;    // number of illegal letters changed. <= k    int changed = 0;    while(r < n) {        assert(changed <= k);        assert(l <= r);        if (s[r] == c) { r++; } // legal, extend.        else {            // need to change a letter to extend, s[r] != c.            if (changed == k) {                // cannot extend, contract from left.                if (s[l] != c) { changed--; }                l++;            } else {                // extend, spending a change.                r++;                changed++;            }        }        // keep track of best window size.        best = max(best, r-l);    }}

Unfortunately, the above code is flawed. It does not work when the window size is zero. (TODO: explain) on the other hand, the implementation where we always stride forward with the r value in a for loop, and only deciding what happens with l does not suffer from this ( link to implementation ):

int best = 0;for(int c = 'a'; c <= 'b'; ++c) {    int l = 0;    // number of illegal letters changed. <= k    int changed = 0;    // [l, r]    for(int r = 0; r < n; ++r) {        // change to 'a'.        if (s[r] != c) { changed++; }        // maintain invariants: must have changed <= k,        // and at the end of a loop trip, we must have l <= r.        while(changed > k && l < r) {            if (s[l] != c) { changed--; }            l++;        }        assert(l <= r);        // keep track of best window size.        best = max(best, r-l+1);    }}