Sliding Window

I been reading, watching videos and experimenting with the Universal Windows Platform (UWP) and cpp/WinRT most of the day. On this final block I decided to take a break and make a post in my blog. I want to get some software done before the end of the day this Wednesday. Will let you know if I meet the deadline.

I noticed in my Gmail that JAVAAID had posted a video on YouTube titled “Sliding Windows Technique”. It called my attention because the Rabin-Karp algorithm is based on a sliding window technique.  In the past few months I wrote a post on the subject and named it “Rabin-Karp Algorithm” (not too creative on my part).

I just took a break after my fourth 2-hour block of the day. I wake up at 05:00 AM so I can get on average 10 hours per working day and 4 hours on weekend days. Mondays is garbage collection day and this week we had regular garbage and recycling. Earlier today I brought in the garbage bin. A few minutes ago I went out to bring in the recycle bin. My neighbors to the right were stringing holiday light on their trees. The current temperature is about 43 degrees Fahrenheit but the wind is blowing. Combined the wind chill is 35 degrees. Both are wearing hats, gloves, jackets and seem to be quite cold. I guess they do have the holiday spirit.

Enough chitchat and let’s get to the subject at hand. The idea is to compute a value using a set of contiguous entries in an array. Then move the window in a specific direction updating the running value with the first and last elements in the window.

In this case the idea is to get the largest sum of a set of consecutive numbers in an integer array.

6
2 1 5 1 3 2
3
main <<< n: 6
main <<< arr: [2 1 5 1 3 2]
main <<< k: 3
slidingWindow <<< maxSum: 8
slidingWindow <<< i: 0 j: 3 sum: 7 maxSum: 8
slidingWindow <<< i: 1 j: 4 sum: 9 maxSum: 9
slidingWindow <<< i: 2 j: 5 sum: 6 maxSum: 9
main <<< maxSum: 9


8
1 9 -1 -2 7 3 -1 2
4
main <<< n: 8
main <<< arr: [1 9 -1 -2 7 3 -1 2]
main <<< k: 4
slidingWindow <<< maxSum: 7
slidingWindow <<< i: 0 j: 4 sum: 13 maxSum: 13
slidingWindow <<< i: 1 j: 5 sum: 7 maxSum: 13
slidingWindow <<< i: 2 j: 6 sum: 7 maxSum: 13
slidingWindow <<< i: 3 j: 7 sum: 11 maxSum: 13
main <<< maxSum: 13

I have captured two runs of the solution using the same sets of values (but in different order) used by JAVAAID. The reason for this being is that I wrote my code and then I watched the rest of the video once I had enough information to craft an approach.

The first number holds the number of entries in the array of integers that follows. The second line holds the values for the array. The third line contains the number of elements that need to be process per step. Put in other words, given an array of integers determine the value of the largest sum of three consecutive numbers.

The first set adds up to (2 + 1 + 5 == 8) eight. The second to 7, the third to 9 and the fourth and last to 6. The expected result is nine. It seems that the method returns the proper answer.

We repeat the test with a different set which also includes negative numbers. It seems that the expected result is 13 and that is what the algorithm returns.

There is a brute force approach which I skipped. If interested, you can see the implementation in the YouTube video by JAVAAID.

I am on a roll using Visual Studio Code. Interesting enough, last week I installed a licensed version of Visual Studio 2019 Enterprise edition in one of my development machines. I needed that version to get past an issue that I encountered while using Visual Studio 2017 Enterprise edition. Long story, but when you are working with tools that are evolving, you tend to encounter issues with things that are supposed to work on a new version but have not been implemented in an older one.

I am working with C++ on the project I mentioned earlier in this post, but for this post I went with Java and I used the Visual Studio Code IDE.

C:\>cd C:\Users\John\workspace6

C:\Users\John\workspace6>mkdir SlidingWindow

C:\Users\John\workspace6>dir
 Volume in drive C is OS
 Volume Serial Number is 26E8-87B0

 Directory of C:\Users\John\workspace6

11/25/2019  12:56 PM    <DIR>          .
11/25/2019  12:56 PM    <DIR>          ..
10/23/2019  11:06 AM    <DIR>          .metadata
05/11/2019  07:13 AM    <DIR>          .recommenders
05/22/2019  08:05 AM    <DIR>          10of50
05/11/2019  07:07 AM    <DIR>          AbsolutePermutation
10/17/2019  06:47 AM    <DIR>          AddWithoutPlus
06/12/2019  10:40 AM    <DIR>          ArraysLeftRotation
10/19/2019  06:50 AM    <DIR>          BabyNames
07/22/2019  02:09 PM    <DIR>          Boggle
05/13/2019  02:11 PM    <DIR>          Bomberman
10/16/2019  01:05 PM    <DIR>          BreakingRecords
09/14/2019  05:52 AM    <DIR>          BSTOperations
11/20/2019  04:12 PM    <DIR>          CatsAndMouse
10/09/2019  01:57 PM    <DIR>          CircularQUsingLinkedList
07/25/2019  12:47 PM    <DIR>          FindDamaged
11/09/2019  07:05 AM    <DIR>          GraphSearch
10/30/2019  11:53 AM    <DIR>          HashMapList
06/10/2019  02:19 PM    <DIR>          HashMapVSHashtable
08/24/2019  08:36 AM    <DIR>          IsUnique
08/26/2019  03:38 PM    <DIR>          LinkedLists
10/15/2019  05:27 AM    <DIR>          ListClass
06/17/2019  10:54 AM    <DIR>          ListsAndSets
10/23/2019  06:23 AM    <DIR>          Majority Element
10/18/2019  05:57 AM    <DIR>          MissingNumber
10/29/2019  09:38 AM    <DIR>          MissingTwo
06/10/2019  01:18 PM    <DIR>          OverridePrivate
10/15/2019  10:21 AM    <DIR>          PlaneRoutes
06/20/2019  10:07 AM    <DIR>          PrefixSum
08/10/2019  06:18 AM    <DIR>          RabinKarpAlgorithm
10/25/2019  05:43 AM    <DIR>          ReSpace
08/31/2019  05:30 AM    <DIR>          ReverseString
06/12/2019  09:53 AM    <DIR>          SimpleArraySum
11/25/2019  12:56 PM    <DIR>          SlidingWindow        <===
09/03/2019  04:10 PM    <DIR>          Stack
09/03/2019  04:10 PM    <DIR>          StackAndQueue
08/31/2019  09:22 AM    <DIR>          StackArray
09/09/2019  03:37 PM    <DIR>          StackMin
11/17/2019  06:52 AM    <DIR>          StaticInitializer
09/16/2019  04:28 PM    <DIR>          TestInput
10/28/2019  01:08 PM    <DIR>          TheMasseuse
09/07/2019  05:40 AM    <DIR>          ThreeInOne
09/11/2019  03:02 PM    <DIR>          TreesAndGraphs
10/23/2019  06:56 AM    <DIR>          TriesHashMap
10/30/2019  06:45 AM    <DIR>          WordTransformer
               0 File(s)              0 bytes
              45 Dir(s)  548,106,178,560 bytes free

To start I created a folder in which I implemented the code for this post.

  //
  // Test scaffolding.
  //
  public static void main(String[] args) {

    // **** open scanner ****
    Scanner sc = new Scanner(System.in);

    // **** read number of integers in array ****
    int n = sc.nextInt();

    // ???? ????
    System.out.println("main <<< n: " + n);

    // **** allocate array of integers ****
    int[] arr = new int[n];

    // **** read array of integers ****
    for (int i = 0; i < n; i++) {
      arr[i] = sc.nextInt();
    }

    // ???? ????
    System.out.print("main <<< arr: [");
    for (int i = 0; i < arr.length; i++) {
      if (i < (arr.length - 1))
        System.out.print(arr[i] + " ");
      else
        System.out.print(arr[i]);
    }
    System.out.println("]");

    // **** read k ****
    int k = sc.nextInt();

    // ???? ????
    System.out.println("main <<< k: " + k);

    // **** close scanner ****
    sc.close();

    // **** ****
    System.out.println("main <<< maxSum: " + slidingWindow(arr, k));
  }

The test scaffolding is implemented in the main function. As usual I tend to include debug statements in my code. Of course in this short code and most important, while using an IDE and you can single step, debug statements are of reduced value.

  ///
  ///
  ///
  static int slidingWindow(int[] arr, int k) {

    // **** compute the initial max sum (first k elements) ****
    int maxSum = 0;
    for (int i = 0; i < k; i++)
      maxSum += arr[i];

    // ???? ????
    System.out.println("slidingWindow <<< maxSum: " + maxSum);

    // **** loop updating the max sum ****
    int sum = maxSum;
    for (int i = k; i < arr.length; i++) { // **** update the sum **** sum += (-arr[i - k] + arr[i]); // ***** update the max sum (if needed) **** if (sum > maxSum)
        maxSum = sum;

      // ???? ????
      System.out.println("slidingWindow <<< i: " + i + " sum: " + sum + " maxSum: " + maxSum);
    }

    // **** return the max sum ****
    return maxSum;
  }

We pass the array of integers and the number of integers to add at a time. We then compute the sum of the first k values in the array. At this point we are ready to start a loop to traverse the array computing the highest / maximum sum.

We loop and update a local sum that was initialized to the sum of the first k elements. On each loop we remove the value of the leftmost element from the set and include the next rightmost element. This implements a sliding window.

After we compute the new sum, we compare it against the running sum. If the new value is larger we replace the running value and keep on looping. As you can see the algorithm has a O(n) running time.

The entire code for this project can be found in my GitHub repository.

If you have comments or questions regarding this, or any other post in this blog, or if you would like for me to serve of assistance with any phase in the SDLC (Software Development Life Cycle) of a project associated with a product or service, please do not hesitate and leave me a note below. If you prefer, send me a message using the following address:  john.canessa@gmail.com. All messages will remain private.

Keep on reading and experimenting. It is the best way to learn, refresh your knowledge and enhance your developer toolset!

John

Follow me on Twitter:  @john_canessa

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.