0

I was attempting the Leetcode Problem 239(Sliding Window Maximum).
Consider the two implementations, Sol1 and Sol2. Sol1:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int> dq;
        vector<int> ans;
        for (int i=0; i<nums.size(); i++) {
            if (!dq.empty() && dq.back() == i-k) dq.pop_back();
            while (!dq.empty() && nums[dq.front()] < nums[i]) dq.pop_front();
            dq.push_front(i);
            if (i>=k-1) ans.push_back(nums[dq.back()]);
        }
        return ans;
    }
};

Sol2:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        deque<int> dq;
        vector<int> ans;
        for (int i=0; i<nums.size(); i++) {
            if (!dq.empty() && dq.front() == i-k) dq.pop_front();
            while (!dq.empty() && nums[dq.back()] < nums[i]) dq.pop_back();
            dq.push_back(i);
            if (i>=k-1) ans.push_back(nums[dq.front()]);
        }
        return ans;
    }
};

Sol2 differs from Sol1 in these ways:

  • The back() method of the deque has been changed to front() and vice versa.
  • The push_front() method of the deque has been changed to push_back() and vice versa.
  • The pop_front() method of the deque has been changed to pop_back() and vice versa. Logically, these two implementations are similar.

According to the C++ deque implementation,

The complexity (efficiency) of common operations on deques is as follows:

  • Random access - constant O(1)
  • Insertion or removal of elements at the end or beginning - constant O(1)
  • Insertion or removal of elements - linear O(n)

But I observed a significant difference in the time and memory consumed by these implementations. I tried to check with few compilers, the differences are still there.

The results and the entire code used for testing can be found in this gist. Why is there a difference between the 2 implementations (Sol1 and Sol2)? There is also a difference when we use different compilers. I am not able to figure this out. Any help is appreciated.

Sharvani
  • 11
  • 3
  • 1
    How do you measure the time and memory consumption? Do you remember to measure on an *optimized* build? And how many times did you measure each? For better results always measure many (*many*) times and take the average. And lastly, are you sure you measure only the code shown? There no other code in the program which could affect your measurements? – Some programmer dude Dec 14 '21 at 07:08
  • 2
    Leetcode measures are most likely very noisy and inaccurate. – Evg Dec 14 '21 at 07:16
  • @Someprogrammerdude Actually, I didn't mean to exactly compute the time and memory. I wanted to check if the differences between the two solutions would remain significant in each case. I had run the code few times to measure the time, but mentioned one set of results. Agreed, average is a better measure. Yes, other lines of code apart from the Solution class could affect the measurements, but not in the difference between the measurements of the 2 Solution implementations right? – Sharvani Dec 14 '21 at 07:16
  • 1
    Do you measure with enabled optimizations? Also, note that your program has no observable behavior (other than its exit status 0). Without observable behavior, a compiler may generate practically no machine code. – Daniel Langr Dec 14 '21 at 07:19
  • @DanielLangr for the results obtained from the gcc compilers, I haven't used any. I'm not sure about the code used in Leetcode internally(as we can just modify the Solution class over there). Can you explain more on how the observable behavior could make any difference? – Sharvani Dec 14 '21 at 07:27
  • @clrnr132453 Under so-called _as-if_ rule, a compiler needs to generate machine code that provides the observable behavior which is prescribed to some source code by the C++ standard. If there is no observable behavior prescribed, no machine code may be generated. Anyway, measuring unoptimized builds typically does not make sense. – Daniel Langr Dec 14 '21 at 07:31
  • 4
    Leetcode is very bad at reporting time and memory (you're running on a shared system). For real performance measurements you need to profile on a controlled system. Most likely the result will also depend on the compiler and STL implementation used. My advise if you want to learn C++ is to stay away from leetcode alltogether (its more about problem solving then about how to write good code anyway) and use local development tools like debuggers/profilers and the like and measure always measure (the results may even depend on the input data characteristics) – Pepijn Kramer Dec 14 '21 at 08:29

0 Answers0