<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Shreyash Rai — #neetcode</title><description>Everything tagged “neetcode”.</description><link>https://shreyashrai.com</link><item><title>Two pointers</title><link>https://shreyashrai.com/til/b-two-pointers</link><guid isPermaLink="true">https://shreyashrai.com/til/b-two-pointers</guid><pubDate>Thu, 09 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The two pointer approach is useful when you are tired of O(n2) solutions and multiple passes over the same data. You use two different pointers, and converge to the solution based on the problem. But the problem with it, is that the approach is same but framing is different for each problem. These can be categorized in three buckets:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Scan &amp;amp; Verify:&lt;/strong&gt; When you use two pointers just for checking a condition (such as in &lt;a href=&quot;#1-valid-palindrome&quot;&gt;Valid Palindrome&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Comparing against a target:&lt;/strong&gt; When you use two pointers to look for a solution that satisfies a target. Whatever brings you closer to the target, go there (such as in &lt;a href=&quot;#2-two-sum-ii---sorted-array&quot;&gt;Two Sum II&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exchange-argument optimization:&lt;/strong&gt; When you have no fixed target, but you&apos;re optimizing a solution, such as looking for a maximum. Used in both &lt;a href=&quot;#4-container-with-most-water&quot;&gt;Container with most water&lt;/a&gt; and &lt;a href=&quot;#5-trapping-rain-water&quot;&gt;Trapping Rain Water&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;1. Valid Palindrome&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool isAlpha(char&amp;amp; c){
        if (c &amp;gt; 64 &amp;amp;&amp;amp; c &amp;lt; 91) {
            c = c + 32;
            return true;
        }
        if (c &amp;gt; 96 &amp;amp;&amp;amp; c &amp;lt; 123) return true;
        if (c &amp;gt; 47 &amp;amp;&amp;amp; c &amp;lt; 58) return true;
        return false;
    }
    
    bool isPalindrome(string s) {
        int n = s.size();
        int i = 0;
        int j = n-1;
        while (i&amp;lt;j){
            if (!isAlpha(s[i])) {
                i++;
                continue;
            }
            if (!isAlpha(s[j])){
                j--;
                continue;
            }
            if (s[i] != s[j]) return false;
            i++;
            j--;
        }
        return true;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problems I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;I mean. Strings. I know they are arrays, but that isn&apos;t the problem anymore.&lt;/li&gt;
&lt;li&gt;This question was slightly different, because we were given alphanumeric characters only. They are all the english alphabets, and the numbers 0-9.&lt;/li&gt;
&lt;li&gt;I had to look up the ranges of these characters, and then I found out that the strings would contain spaces as well. So I thought let&apos;s create a new function itself, which will check if it is alphanumeric or not.&lt;/li&gt;
&lt;li&gt;Even though the question said it was case-insensitive, I still converted the capital letters to small letters by adding 32 to the ascii values. (I forgot it was case insensitive but I don&apos;t regret it).&lt;/li&gt;
&lt;li&gt;I forgot to add &lt;code&gt;continue&lt;/code&gt; in the if conditions and ended up checking the equality each time even after &lt;code&gt;i&lt;/code&gt; or &lt;code&gt;j&lt;/code&gt; changed. I thought it would work without continue, because the &lt;code&gt;if&lt;/code&gt; conditions before it ensured that i and j pointed to alphanumeric characters only.&lt;/li&gt;
&lt;li&gt;Two pointers isn&apos;t new to me. The previous array questions had me doing things in one passes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be done better?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Clearly this solution is inefficient. First off, I created a separate function that let&apos;s me check for alphanumeric. I didn&apos;t know the library function which is &lt;code&gt;isalnum()&lt;/code&gt; from &lt;code&gt;&amp;lt;cctype&amp;gt;&lt;/code&gt; library. And adding 32 to ascii values can be replaced with &lt;code&gt;tolower()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then that function I wrote also changes uppercase to lowercase automatically, so even though I made it deliberately, it&apos;s better to write readable code that doesn&apos;t do what it&apos;s name says it does. Again, if I did want uppercase values then I&apos;d have removed it, but no one would know.&lt;/li&gt;
&lt;li&gt;Case insensitive means &apos;A&apos; and &apos;a&apos; are treated the same. So in this question, since both ascii values would still be different, I need to convert one into the other. If it was case sensitive, then I wouldn&apos;t have to because I&apos;d need to make sure &apos;A&apos; matches only &apos;A&apos; and not &apos;a&apos;.&lt;/li&gt;
&lt;li&gt;Then, one gotcha. Both &lt;code&gt;isalnum()&lt;/code&gt; and &lt;code&gt;tolower()&lt;/code&gt; require a &lt;code&gt;unsigned char&lt;/code&gt; (non-negative) and &lt;code&gt;char&lt;/code&gt; is sometimes negative too. This would throw an undefined behaviour (UB).&lt;/li&gt;
&lt;li&gt;Something called &lt;em&gt;casting&lt;/em&gt; saves that. It converts signed stuff to unsigned stuff. So, we do &lt;code&gt;isalnum(static_cast&amp;lt;unsigned char&amp;gt;(c))&lt;/code&gt; and &lt;code&gt;tolower(static_cast&amp;lt;unsigned char&amp;gt;(c))&lt;/code&gt;. This converts a negative c into the right ascii value (0-255). By conversion, we mean &lt;em&gt;&quot;Reading the same bits differently&quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Complexity? We only operated O(n) times. And O(1) space because we didn&apos;t create anything.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;About casting&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Casting is done when you need to &lt;em&gt;reinterpret&lt;/em&gt; a datatype into another data type.&lt;/li&gt;
&lt;li&gt;In C, we could typecast something with &lt;code&gt;(datatype) expression&lt;/code&gt; like &lt;code&gt;(int)myFloat&lt;/code&gt; but this is quite vague for the different reasons it can fail. So C++ adds 4 different types of casting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static Casting:&lt;/strong&gt; Converts between compatible/related types. Done during compile time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic Casting:&lt;/strong&gt; Safely downcasts inside polymorphic hierarchies. These are in classes with atleast one virtual function. But since I can&apos;t remember OOPs concepts, I will box this for later.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Const Casting:&lt;/strong&gt; Adds or removes const or volatile qualifiers. Meaning if I termed some variable as unchangeable, then changing that can cause issues in complex codes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reinterpret Casting:&lt;/strong&gt; This is low-level, aka close to machine language, aka playing with memory. It directs the compiler to interpret raw binary memory bits of an expression exactly as if it were a totally distinct data type.&lt;/li&gt;
&lt;li&gt;Anyways, we care about static_cast, useful for converting ints to floats, signed to unsigned, changes inheritance from a derived class to a base class. It checks at compile time, and if just isn&apos;t possible (like int to struct) it won&apos;t compile. But IT WILL COMPILE and not throw error if we did something that&apos;s fine for a computer but logically not right. Like converting a double into an int. This will lose the decimal.&lt;/li&gt;
&lt;li&gt;Anyways, here&apos;s the final codes.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool isPalindrome(string s) {
        int n = s.size();
        int i = 0;
        int j = n-1;
        while (i&amp;lt;j){
            if (!isalnum(static_cast&amp;lt;unsigned char&amp;gt;(s[i]))) {
                i++;
                continue;
            }
            if (!isalnum(static_cast&amp;lt;unsigned char&amp;gt;(s[j]))){
                j--;
                continue;
            }
            if (tolower(static_cast&amp;lt;unsigned char&amp;gt;(s[i])) != tolower(static_cast&amp;lt;unsigned char&amp;gt;(s[j]))) return false;
            i++;
            j--;
        }
        return true;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Two Sum II - sorted array&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;int&amp;gt; twoSum(vector&amp;lt;int&amp;gt;&amp;amp; nums, int target) {
        int i=0;
        int j = nums.size()-1;
        while(nums[i] + nums[j] != target){
            int sum = nums[i] + nums[j];
            if (sum &amp;gt; target){
                j--;
                continue;
            }
            if (sum &amp;lt; target){
                i++;
                continue;
            }
        }
        return {i+1, j+1};

    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problems I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;NONE! The code run perfectly and got submitted in one try.&lt;/li&gt;
&lt;li&gt;At first I thought I&apos;d use the slow/fast thingy, but it was skipping elements in my head. Then binary search where I&apos;d half i or j but that still skipped elements and never known whether increasing i or decreasing j would give a higher or lower target. So didn&apos;t attempt that either.&lt;/li&gt;
&lt;li&gt;Simply, increase i and decrease j, array is sorted so we know we are converging by checking the inequality against sum. We didn&apos;t have that in normal two sum, where numbers were random and we didn&apos;t know which pointer to change.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be made better?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;This solution worked because we were guaranteed a solution. But if there wasn&apos;t, the equality would need to be &lt;code&gt;i&amp;lt;j&lt;/code&gt; so we know it ends even after checking all possible elements through individual work of i and j.&lt;/li&gt;
&lt;li&gt;Instead of continue, we can cleanly write if else statements since we don&apos;t check AFTER the ifs but before them.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;int&amp;gt; twoSum(vector&amp;lt;int&amp;gt;&amp;amp; nums, int target) {
        int i=0;
        int j = nums.size()-1;
        while(i&amp;lt;j){
            int sum = nums[i] + nums[j];
            if (sum == target) return {i+1, j+1};
            else if (sum &amp;gt; target) j--;
            else i++;
        }
        return {};
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 3sum&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; threeSum(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        sort(nums.begin(), nums.end());
        set&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; answer;
        int i = 0;
        while (i &amp;lt; nums.size()-2){
            int j = i+1;
            int k = nums.size() - 1;
            while (j &amp;lt; k){
                if (nums[i] + nums[j] + nums[k] &amp;lt; 0) j++;
                else if (nums[i] + nums[j] + nums[k] &amp;gt; 0) k--;
                else {
                    answer.insert({nums[i], nums[j], nums[k]});
                    j++;
                }
            }
            i++;
        }

        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; output;
        for (const auto&amp;amp; x : answer){
            output.push_back(x);
        }
        return output;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problems I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;A lot of problems were faced. At first, I was so confused on what to do. Then thought of the approach of i++, j--, and loop between them. I was trying really hard to not have a O(n3) solution. But this was skipping elements again because i and j are moving to the center at the same rate and we would miss elements that are skewed on the backward side. Like elements that didn&apos;t get included due to change in i or j before we tried all combinations.&lt;/li&gt;
&lt;li&gt;However, this error only came after it worked for a few test cases and gave me a duplication output. So, in the final output vector I needed unique elements. I thought I&apos;d create an &lt;code&gt;unordered_set&lt;/code&gt; but apparently it doesn&apos;t store and compare vectors well. I looked up, it was asking me to create a custom differentiator function which I have no idea about, but then I was told that normal &lt;code&gt;set&lt;/code&gt; works with vectors and I did that.&lt;/li&gt;
&lt;li&gt;The final solution I conjured up where I&apos;d have one outer loop for &lt;code&gt;i&lt;/code&gt; and do the same two pointer approach for two sum on a sorted array.&lt;/li&gt;
&lt;li&gt;Time complexity: O(n2.logm) where m is number of elements in set. Insert operation is costing me. Space: O(n)&lt;/li&gt;
&lt;li&gt;I am completely aware that this solution is inefficient. But I&apos;m at least glad I solved it myself.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be made better?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Alright so my solution can be improved by skipping the duplication.  Set doesn&apos;t allow duplicates yes, but due to insert operation we were suffering. Instead we can just skip the duplicate numbers AS we encounter them in the array.&lt;/li&gt;
&lt;li&gt;The initial check for &lt;code&gt;i&lt;/code&gt; we check whether the previous number at &lt;code&gt;i-1&lt;/code&gt; is same as &lt;code&gt;i&lt;/code&gt; and if it is, we skip it.&lt;/li&gt;
&lt;li&gt;When we find a new &lt;code&gt;i&lt;/code&gt; then start with two pointers &lt;code&gt;j&lt;/code&gt; and &lt;code&gt;k&lt;/code&gt;, do the testing and when we have found a triplet, it&apos;s possible the elements near &lt;code&gt;j&lt;/code&gt; and &lt;code&gt;k&lt;/code&gt; are same (since array was sorted) and we should skip them since they would only form duplicate triplets.&lt;/li&gt;
&lt;li&gt;Another skipping mechanic, the moment &lt;code&gt;i&lt;/code&gt; points to something more than 0, then j and k are also greater than 0 and we can possible not have any more triplets. So we end early.&lt;/li&gt;
&lt;li&gt;No set this time, only a vector. So O(n) space. O(n2) time because no insert operation.&lt;/li&gt;
&lt;li&gt;Here&apos;s the more efficient solution.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; threeSum(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        sort(nums.begin(), nums.end());
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; output;
        int i = 0;
        while (i &amp;lt; nums.size()-2){
            if (nums[i] &amp;gt; 0) break;
            if (i &amp;gt; 0 &amp;amp;&amp;amp; nums[i] == nums[i-1]) {
                i++;
                continue;
            }
            int j = i+1;
            int k = nums.size() - 1;
            while (j &amp;lt; k){
                int sum = nums[i] + nums[j] + nums[k];
                if (sum &amp;lt; 0) j++;
                else if (sum &amp;gt; 0) k--;
                else {
                    output.push_back({nums[i], nums[j], nums[k]});
                    j++;
                    k--;
                    while (j&amp;lt;k &amp;amp;&amp;amp; nums[j] == nums[j-1]) j++;
                    while (j&amp;lt;k &amp;amp;&amp;amp; nums[k] == nums[k+1]) k--;
                }
            }
            i++;
        }
        return output;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. Container With Most Water&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    int maxArea(vector&amp;lt;int&amp;gt;&amp;amp; h) {
        int n = h.size();
        int i = 0;
        int j = n-1;
        int maxi = 0;
        while (i &amp;lt; j){
            int area = (j-i)*min(h[i], h[j]);
            maxi = max(area, maxi);
            if (h[i]&amp;lt;h[j]) i++;
            else j--;
        }
        return maxi;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problem I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;I was not able to solve this problem myself. After trying really hard to think of a solution, I only managed to think of the idea of moving TOWARDS the height that gave me a higher water value. If i++ gave me a higher water than j-- than I&apos;d move forward with i++ and not j-- then repeat, while storing the absolute max. But this didn&apos;t work. It wasn&apos;t converging to the best pair.&lt;/li&gt;
&lt;li&gt;I had to look up the hints in the problem. It told me that you only move the index that was the lesser one than the other. Because if we didn&apos;t move it, the absolute max that this height can give is lesser than before because width would be lower. So we need to change this one, and keep the other longer height same. Slowly, both height bars would be bigger than before.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Why it works&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;You see, this works because in the two pointer approach, convergence is only guaranteed if you do something that&apos;s better, or if you do something that is the reverse of what isn&apos;t working. This problem is the latter. Because moving the lower tower is the only way you can have a different answer than the current one, which might be better. If we moved the higher tower first, the score would still be at most the other lower height (but lower width, so probably worse!).&lt;/li&gt;
&lt;li&gt;Since we did the opposite, and also checked each possibility too (because either i or j moves until we reach the best, because there will always be one lower tower) we converged.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. Trapping rain water&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    int trap(vector&amp;lt;int&amp;gt;&amp;amp; height) {

        int n = height.size();
        vector&amp;lt;int&amp;gt; water;
        for (int i =0; i &amp;lt; n; i++){
            int l=0;
            int r=0;
            for (int j = 0; j &amp;lt; i; j++){
                l = max(l, height[j]);
            }
            for (int j = i+1; j &amp;lt; n; j++){
                r = max(r, height[j]);
            }
            water.push_back(max(min(l,r)-height[i], 0));
        }
        int sum = 0;
        for (int x : water){
            sum += x;
        }
        return sum;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problems I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Well clearly this is a hard problem. I was completely lost on what to do.&lt;/li&gt;
&lt;li&gt;I had to look up at the hints, which gave me the idea of how to calculate the height of water at each index. It clicked, and wrote this solution&lt;/li&gt;
&lt;li&gt;But it pains me that this is an O(n2) solution. The question said it should be at most or better than O(n).&lt;/li&gt;
&lt;li&gt;My solution does not contain anything related to two pointers.&lt;/li&gt;
&lt;li&gt;But wait, I can replace it! Let&apos;s code it!!!!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    int trap(vector&amp;lt;int&amp;gt;&amp;amp; height) {

    int n = height.size();
    vector&amp;lt;int&amp;gt; water;
    int l=0;
    for (int i=0; i &amp;lt; n; i++){
        l = max(l, height[i]);
        water.push_back(l);
    }
    // now water vector contains best heights from the left
    // we can directly compute right best and amount of water now
    int r = 0;
    for (int i=n-1; i &amp;gt;=0; i--){
        water[i] = (max(0, min(r, water[i])-height[i]));
        r = max(r, height[i]);
    }

    int sum = 0;
    for (int x : water){
        sum += x;
    }
    return sum;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;LETS GOOOOOO!!!&lt;/li&gt;
&lt;li&gt;But this is still not using two pointer approach. This is still two passes. What else can we think of?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be done better?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Yeah so this better solution is quite hard to see.&lt;/li&gt;
&lt;li&gt;First see the solution.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    int trap(vector&amp;lt;int&amp;gt;&amp;amp; height) {
    int n = height.size();
    int totalwater = 0;
    int l = 0;
    int r = n - 1;
    int leftMax = 0;
    int rightMax = 0;
    while (l&amp;lt;r){
        if (height[l] &amp;lt; height[r]){
            leftMax = max(leftMax, height[l]);
            totalwater += leftMax - height[l];
            l++;
        }
        else {
            rightMax = max(rightMax, height[r]);
            totalwater += rightMax - height[r];
            r--;
        }
    }
    return totalwater;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;We only move the index of the bar with the lower height again.&lt;/li&gt;
&lt;li&gt;We only process the left side when &lt;code&gt;height[l] &amp;lt; height[r]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;So whatever we have at &lt;code&gt;l&lt;/code&gt;, we calculate the water there. &lt;code&gt;leftMax&lt;/code&gt; contains the best height before current &lt;code&gt;l&lt;/code&gt;. We calculate total water by &lt;code&gt;leftMax - current_height&lt;/code&gt; without looking at the right side. Why? Because it was guaranteed that &lt;code&gt;height[l] &amp;lt; height[r]&lt;/code&gt; making left the only bottleneck. You&apos;d wonder &lt;em&gt;what if height[r] was lower than leftMax?&lt;/em&gt; which is the confusing part. But the solution would never reach that point because we cannot get &lt;code&gt;leftMax &amp;gt; height[r]&lt;/code&gt;. The movement of &lt;code&gt;l&lt;/code&gt; and &lt;code&gt;r&lt;/code&gt; is such that that condition never arrives. leftMax must&apos;ve been processed before, meaning &lt;code&gt;l&lt;/code&gt; was at &lt;code&gt;leftMax&lt;/code&gt; sometime before, and we only got leftMax value when some &lt;code&gt;height[r]&lt;/code&gt; was already bigger. Now &lt;code&gt;r&lt;/code&gt; didn&apos;t move, and it only moves when &lt;code&gt;height[l]&lt;/code&gt; is higher than &lt;code&gt;height[r]&lt;/code&gt; which can only be lesser than or equal to the previous rightMax. So leftMax never grew past it&apos;s big &lt;code&gt;height[r]&lt;/code&gt; and is already higher than current &lt;code&gt;height[l]&lt;/code&gt;. Meaning we right side is bigger than left side, and left side is the bottle neck.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>C++</category><category>Neetcode</category><category>DSA</category></item><item><title>Arrays and Hashing</title><link>https://shreyashrai.com/til/a-arrays-and-hashing</link><guid isPermaLink="true">https://shreyashrai.com/til/a-arrays-and-hashing</guid><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Arrays and Hashing&lt;/h2&gt;
&lt;h3&gt;1. Contains duplicate&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool hasDuplicate(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        set&amp;lt;int&amp;gt; myset;
        for (int i=0; i &amp;lt; nums.size(); i++){
            int temp = myset.size();
            myset.insert(nums[i]);
            if (temp == myset.size()) return true;
        }
        return false;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Time Complexity: &lt;code&gt;O(nlogn)&lt;/code&gt; because I used &lt;code&gt;set&lt;/code&gt;, which uses binary search trees and is ordered. It&apos;s insert operation is &lt;code&gt;O(logn)&lt;/code&gt; so doing it n times = &lt;code&gt;O(nlogn)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Space Complexity: &lt;code&gt;O(n)&lt;/code&gt;, size of set.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be made better?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;As &lt;code&gt;set&lt;/code&gt; is basically BST, it&apos;s tree operations take &lt;code&gt;logn&lt;/code&gt; time. Instead use a hash table (&lt;code&gt;unordered_set&lt;/code&gt;) which is basically a bucket system, and it&apos;s operations are in average case &lt;code&gt;O(1)&lt;/code&gt;. Close because the worst case is &lt;code&gt;O(n)&lt;/code&gt; if all the elements collide into ONE bucket.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;New things&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Insert&lt;/code&gt;: is an [[API]], it &lt;em&gt;returns&lt;/em&gt; a &lt;code&gt;pair&amp;lt;iterator, bool&amp;gt;&lt;/code&gt; where iterator is basically a pointer to either the new element added (in which case bool is &lt;code&gt;true&lt;/code&gt;) or the already existing element that didn&apos;t get inserted again (bool being &lt;code&gt;false&lt;/code&gt;). Thus, without checking for size in each loop, we could just check if the &lt;code&gt;pair.second&lt;/code&gt; value was false.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count&lt;/code&gt; and &lt;code&gt;contains&lt;/code&gt; can become alternatives for the if condition, checking if the set contained the element already. But &lt;code&gt;insert.second&lt;/code&gt; is much cleaner.&lt;/li&gt;
&lt;li&gt;Count: &lt;code&gt;.count(number)&lt;/code&gt; gives how many times number appeared in the container. For sets and unordered_sets it is either 0 or 1 because each element is unique. So we could use this too.&lt;/li&gt;
&lt;li&gt;Contains (for newer C++20): &lt;code&gt;.contains(number)&lt;/code&gt; is a boolean function that returns true if an element exists in the container.&lt;/li&gt;
&lt;li&gt;So instead of &lt;em&gt;&quot;did size increase?&quot;&lt;/em&gt; we could have &lt;em&gt;&quot;is this element already in the set?&quot;&lt;/em&gt; If both output 0 (the element was not there) then insert the element and continue. If both output 1 (the element is already there!) break and return, since this is a duplicate.&lt;/li&gt;
&lt;li&gt;So this would eventually lead us to &lt;code&gt;O(n)&lt;/code&gt; instead of &lt;code&gt;O(nlogn)&lt;/code&gt;!&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Some errors that went unnoticed&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nums.size()&lt;/code&gt; outputs an unsigned integer &lt;code&gt;size_t&lt;/code&gt; (a non-negative number) but in the &lt;code&gt;for&lt;/code&gt; loop, using &lt;code&gt;int i=0&lt;/code&gt; makes i a signed integer. Now usually this is fine. C++ converts i to unsigned integer during the comparison (&lt;code&gt;i &amp;lt; nums.size()&lt;/code&gt;) and it doesn&apos;t break.&lt;/li&gt;
&lt;li&gt;Yet it WILL break in the case where &lt;code&gt;nums.size() = 0&lt;/code&gt; and we compute &lt;code&gt;nums.size() - 1&lt;/code&gt;. The output would not be -1 but some huge number.&lt;/li&gt;
&lt;li&gt;Fix? Use &lt;code&gt;size_t i&lt;/code&gt; OR write loops using elements themselves (&lt;code&gt;for (int x : nums)&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Extras&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;size_t&lt;/code&gt; is a type, just like int, float or bool. The standard library uses it for sizes and indices, which are all non-negative numbers. As &lt;code&gt;.size()&lt;/code&gt; returns &lt;code&gt;size_t&lt;/code&gt;, it&apos;s just better to compare it to an &lt;code&gt;i&lt;/code&gt; which is &lt;code&gt;size_t&lt;/code&gt; and not &lt;code&gt;int&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;auto&lt;/code&gt; is the lazy-guy&apos;s alternative to all. At compile time (when the code is converted to assembly/machine language) auto is decided by the type of what is on the right side of it.&lt;/li&gt;
&lt;li&gt;So if we wanted the pair output of &lt;code&gt;set.insert()&lt;/code&gt; we&apos;d have to create &lt;code&gt;pair&amp;lt;unordered_set&amp;lt;int&amp;gt;::iterator, bool&amp;gt; result = set.insert(number);&lt;/code&gt; but &lt;code&gt;auto result = set.insert(number)&lt;/code&gt; is easy to write.&lt;/li&gt;
&lt;li&gt;Each STL container has its own iterator, and they&apos;re different because of different traversal mechanics used in each container (like set is BST, unordered_set is buckets, vector is contiguous). Each iterator is accessed by &lt;code&gt;container&amp;lt;type&amp;gt;::iterator&lt;/code&gt; and follows the same three buttons. &lt;code&gt;*it&lt;/code&gt; outputs object at location, &lt;code&gt;++it&lt;/code&gt; takes to the next location, and &lt;code&gt;it != cont.end()&lt;/code&gt; asks if we are at the end or not.&lt;/li&gt;
&lt;li&gt;The number -1 for unsigned integer would be 2^64 - 1 (or 2^32 - 1 for 32 bit systems).&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool hasDuplicate(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        unordered_set&amp;lt;int&amp;gt; myset;
        for (size_t i=0; i &amp;lt; nums.size(); i++){
            auto result = myset.insert(nums[i]);
            if (result.second == false) return true;
        }
        return false;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool hasDuplicate(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        unordered_set&amp;lt;int&amp;gt; myset;
        for (size_t i=0; i &amp;lt; nums.size(); i++){
            if (myset.count(nums[i]) == 1) return true;
            myset.insert(nums[i]);
        }
        return false;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Valid Anagram&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool isAnagram(string s, string t) {
        multiset&amp;lt;char&amp;gt; s_set;
        multiset&amp;lt;char&amp;gt; t_set;
        for (char a : s){
            s_set.insert(a);
        }
        for (char b : t){
            t_set.insert(b);
        }
        if (s_set == t_set) return true;
        return false;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Time Complexity: &lt;code&gt;O((n+m)log(n+m))&lt;/code&gt; Space Complexity: &lt;code&gt;O(n+m)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Can be improved by using two other solutions, each using the same concept:
&lt;ul&gt;
&lt;li&gt;Using a hash map, which stores counts of each char&lt;/li&gt;
&lt;li&gt;As characters are only 26 in number, an array of 26 size can store frequency of each character and index can be easily calculated using the trick &lt;code&gt;c - &apos;a&lt;/code&gt; where c is a character.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The concept: As you go along &lt;code&gt;s&lt;/code&gt; increment counts of each character, and as you go along &lt;code&gt;t&lt;/code&gt; decrement counts of each character. If both were anagrams, the hashmap or array would all be containing zeroes. If any is non-zero, then both strings had different number of characters or different characters themselves.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool isAnagram(string s, string t) {
        unordered_map&amp;lt;char, int&amp;gt; freq;
        for (char a : s){
            freq[a]++;
        }
        for (char b : t){
            freq[b]--;
        }
        for (const auto&amp;amp; x : freq){
            if (x.second != 0) return false;
        }
        return true;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool isAnagram(string s, string t) {
        int freq[26] = {0};
        for (char a : s){
            freq[a - &apos;a&apos;]++;
        }
        for (char b : t){
            freq[b - &apos;a&apos;]--;
        }
        for (int x : freq){
            if (x != 0) return false;
        }
        return true;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;New&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;auto&lt;/code&gt; vs &lt;code&gt;auto&amp;amp;&lt;/code&gt;: &lt;code&gt;auto&amp;amp;&lt;/code&gt; is faster because it doesn&apos;t copy the value. It refers to the original value itself. So any modifications to it will modify the original.&lt;/li&gt;
&lt;li&gt;An initial guard of checking both string length would save some time and allow me to write a common &lt;code&gt;for&lt;/code&gt; loop for both increments and decrements.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;const&lt;/code&gt; is used to tell the compiler that this variable will not be modified. Even if you try to, it won&apos;t work.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;const auto&amp;amp;&lt;/code&gt; seems counter intuitive (why would I want to auto&amp;amp; for modifying but const to keep it same) but in reality you get best of both worlds here, as auto&amp;amp; saves time but const stops any accidental modifications to the original value.&lt;/li&gt;
&lt;li&gt;But in all seriousness, these &lt;code&gt;auto&amp;amp;&lt;/code&gt; stuff doesn&apos;t really matter for small data types like int, char, bool but does in strings/vectors or bigger data structures. So auto is fine. Both are same speed for the small data types.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. Two sum&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;int&amp;gt; twoSum(vector&amp;lt;int&amp;gt;&amp;amp; nums, int target) {
        unordered_map&amp;lt;int, int&amp;gt; hash;
        int n = nums.size();
        for (int i = 0; i &amp;lt; n; i++){
            hash[nums[i]] = i;
        }
        for (int i = 0; i &amp;lt; n; i++){
            if (hash.find(target - nums[i]) != hash.end() &amp;amp;&amp;amp; i != hash[target - nums[i]]) return {min(i, hash[target - nums[i]]), max(i, hash[target - nums[i]])};
        }
        return {};
    }
};

&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problems I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Tried a two pointer approach first, incrementing and decrementing one by one but it had a major flaw of ignoring values that aren&apos;t symmetrically placed in the array&lt;/li&gt;
&lt;li&gt;Then I knew I had to use the &lt;code&gt;O(1)&lt;/code&gt; finding ability of &lt;code&gt;hashmaps&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Got confused over &lt;code&gt;unordered_set&lt;/code&gt; and &lt;code&gt;unordered_map&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Had to look up how &lt;code&gt;find()&lt;/code&gt; works and how if it doesn&apos;t work I have to use &lt;code&gt;hash.end()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Problems saving the index, at first tried &lt;code&gt;hash[nums[i]]+=i&lt;/code&gt; assuming it gets created with 0 first then I could add i to it, but later realized I have to literally equate it to &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then only some syntax errors while writing the return value.&lt;/li&gt;
&lt;li&gt;Wanted to use &lt;code&gt;auto&amp;amp; x : nums&lt;/code&gt; but needed index information so had to resort to &lt;code&gt;i&lt;/code&gt;. &lt;code&gt;find()&lt;/code&gt; gave out an iterator (pointer) which is not what I needed. I could dereference it and find the key (the number) using &lt;code&gt;.first&lt;/code&gt; and its index (value) using &lt;code&gt;.second&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Then faced the same index error which I fixed with a simple condition.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What  can be made better&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Even though this is &lt;code&gt;O(n)&lt;/code&gt; it required &lt;em&gt;two&lt;/em&gt; passes (it completed in &lt;code&gt;2n&lt;/code&gt; time) it was still possible to do it in &lt;em&gt;one&lt;/em&gt; pass. &lt;code&gt;n&lt;/code&gt; and &lt;code&gt;2n&lt;/code&gt; don&apos;t matter to Big-O, but one passes achieves the same thing in half the number of operations.&lt;/li&gt;
&lt;li&gt;The possibility being, &lt;em&gt;before you add the current element, check whether its complement is already in the array. If it is, return. If it&apos;s not, add the element in hash map then go to next element.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;This also solves the same-index error as well, because since we are creating the hash map as we go, same index values don&apos;t exist. The moment we find a solution we return.&lt;/li&gt;
&lt;li&gt;It ALSO solves the fact that we have to return the lower index first. Since the current element is the latest one, the complement would already be before it. So its index is automatically lower.&lt;/li&gt;
&lt;li&gt;Why &lt;code&gt;hash.find(x)-&amp;gt;second&lt;/code&gt; is better? Because if I used &lt;code&gt;hash[x]&lt;/code&gt; it would have created a value in the hash map, being 0. This creation is useless and wastes memory. &lt;code&gt;hash.find(x)-&amp;gt;second&lt;/code&gt; doesn&apos;t create anything.&lt;/li&gt;
&lt;li&gt;I could replace &lt;code&gt;hash.find(x) != hash.end()&lt;/code&gt; with &lt;code&gt;hash.contains(x)&lt;/code&gt; which is much cleaner but only available in C++20.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;int&amp;gt; twoSum(vector&amp;lt;int&amp;gt;&amp;amp; nums, int target) {
        unordered_map&amp;lt;int, int&amp;gt; hash;
        int n = nums.size();
        for (int i = 0; i &amp;lt; n; i++){
            int x = target - nums[i];
            if (hash.find(x) != hash.end()) return {hash.find(x)-&amp;gt;second, i};
            hash[nums[i]] = i;
        }
        return {};
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. Group Anagrams&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool testForAnagram(string s1, string s2){
        if (s1.size() != s2.size()) return false;
        unordered_map&amp;lt;char, int&amp;gt; freq;
        for (int i=0; i&amp;lt;s1.size();i++){
            freq[s1[i]]++;
            freq[s2[i]]--;
        }
        for (auto&amp;amp; x : freq){
            if (x.second != 0) return false;
        }
        return true;
    }

    vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt; groupAnagrams(vector&amp;lt;string&amp;gt;&amp;amp; strs) {
        int n = strs.size();
        vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt; output;
        for (int i = 0; i &amp;lt; n; i++){
            output.push_back({strs[i]});
        }
        for (int i = 0; i &amp;lt; output.size(); i++){
            for (int j = 0; j &amp;lt; output.size(); j++){
                if (i != j &amp;amp;&amp;amp; testForAnagram(output[i][0], output[j][0])){
                    output[i].insert(output[i].end(), output[j].begin(), output[j].end());
                    output.erase(output.begin() + j);
                    j--;
                }
            }
        }
        for (int i = 0; i &amp;lt; output.size(); i++){
            if(output[i].size() == 0) {
                output[i] = output.back();
                output.pop_back();
            }
        }
        return output;
    }
};

&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Complexity&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Time: &lt;code&gt;O(n2.k)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Space: &lt;code&gt;O(n.k)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Well at first the problem was hard enough. But I had a feeling I&apos;d be able to at least complete it.&lt;/li&gt;
&lt;li&gt;At first I got the normal anagram function down, the one we did before, in a separate function of its own which I can call anytime. I knew there would be many comparisons this time, so it would be easier to write a function beforehand to stop things from getting messy.&lt;/li&gt;
&lt;li&gt;Then at first I was going for testing each pair of strings, which would be &lt;code&gt;O(n2)&lt;/code&gt; but before I wrote the &lt;code&gt;for&lt;/code&gt; loop I thought combining multiple strings into vectors would be tough. So I thought of a different approach.&lt;/li&gt;
&lt;li&gt;I knew I had to create vectors, so I made the trivial solution of no anagrams at all. This was a vector of vectors each with one string. Next I&apos;d start combining the elements of vectors having the their first elements as anagrams. If the vector had a higher size, the first element would confirm that the other elements in it were anagrams themselves.&lt;/li&gt;
&lt;li&gt;So combining, I had to look up multiple syntaxes. How to insert elements, how to erase elements, how to delete without fucking up everything etc.&lt;/li&gt;
&lt;li&gt;Combined using a method where you grab the second vector and copying all elements inside the first vector. Its syntax was weird (the insert one). Then deleted the second vector. (After seeing a test case fail with heap exceed I realized I had to reduce &lt;code&gt;j&lt;/code&gt; too because of the deletion).&lt;/li&gt;
&lt;li&gt;I also had a problem of selecting which vectors to combine. At first I had &lt;code&gt;j=i+1&lt;/code&gt; as the starting condition, but this soon made it such that I&apos;d forget to check elements before &lt;code&gt;i&lt;/code&gt;. So I just added a guard of &lt;code&gt;i != j&lt;/code&gt; alongside the anagram function and made &lt;code&gt;j&lt;/code&gt; start from 0 every time.&lt;/li&gt;
&lt;li&gt;And? Et voila!&lt;/li&gt;
&lt;li&gt;Clearly this wasn&apos;t the best solution lmfao. But I&apos;m happy I solved it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;The better way&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;The better way is out of this world. It utilizes the concept that &lt;em&gt;all anagrams, once sorted, are the same.&lt;/em&gt; Which means, &lt;em&gt;each anagram has a unique &apos;key&apos;.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;And guess what? We can have buckets of all anagrams under that unique key, always accessible in O(1) time through a hash map. Each anagram can go into its unique key bucket, and finally, we can output these buckets. Mind = blown.&lt;/li&gt;
&lt;li&gt;Let&apos;s try it.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt; groupAnagrams(vector&amp;lt;string&amp;gt;&amp;amp; strs) {
        unordered_map&amp;lt;string, vector&amp;lt;string&amp;gt;&amp;gt; u_keys;
        for (const auto&amp;amp; s : strs){
            string key = s;
            sort(key.begin(), key.end());
            u_keys[key].push_back(s);
        }
        vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt; output;
        for (const auto&amp;amp; [key, group] : u_keys){
            output.push_back(group);
        }
        return output;
    }   
};

&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Time Complexity: &lt;code&gt; O(n.k.log k)&lt;/code&gt; and Space: &lt;code&gt;O(n.k)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A faster solution exists &lt;code&gt;O(n.k)&lt;/code&gt;, where I don&apos;t have to sort. I can create unique keys myself using arrays.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt; groupAnagrams(vector&amp;lt;string&amp;gt;&amp;amp; strs) {
        unordered_map&amp;lt;string, vector&amp;lt;string&amp;gt;&amp;gt; u_keys;
        for (const auto&amp;amp; s : strs){
            int freq[26] = {0};
            for (char c : s){
	            freq[c - &apos;a&apos;]++;
            }
            string key = &quot;&quot;;
            for (int i=0; i &amp;lt; 26; i++){
	            key += &apos;#&apos;;
	            key += to_string(freq[i]);
            }
            u_keys[key].push_back(s);
        }
        vector&amp;lt;vector&amp;lt;string&amp;gt;&amp;gt; output;
        for (const auto&amp;amp; [key, group] : u_keys){
            output.push_back(group);
        }
        return output;
    }   
};  
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Because &lt;code&gt;char&lt;/code&gt; is an integer type, it remembers its ascii value. Meaning if &lt;code&gt;char + int&lt;/code&gt; happens, the output would not be two appended chars but an integer number. When added to the key (a &lt;code&gt;string&lt;/code&gt;) it would add as the ascii equivalent of that integer, so the final key would actually be weird characters. This is bad because this can confuse the key in cases like &lt;code&gt;11#2&lt;/code&gt; and &lt;code&gt;1#12&lt;/code&gt;. Hence why we need a separator &lt;code&gt;#&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. Top K frequent elements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It seems I&apos;m at my mind&apos;s limit, so I&apos;m going to take a break now. Here&apos;s my brute force solution:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;  class Solution {
public:
    vector&amp;lt;int&amp;gt; topKFrequent(vector&amp;lt;int&amp;gt;&amp;amp; nums, int k) {
        unordered_map&amp;lt;int, int&amp;gt; freq;
        for (int x : nums){
            freq[x]++;
        }
        vector&amp;lt;int&amp;gt; output;
        for (int i=0; i&amp;lt;k; i++){
            int maxi=0;
            for (const auto&amp;amp; [key, value] : freq){
                maxi = max(maxi, value);
            }
            for (const auto&amp;amp; [key, value] : freq){
                if (value == maxi){
                    output.push_back(key);
                    freq[key]=0;
                    break;
                }
            }
        }
        return output;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Time Complexity: O(k.n)&lt;/li&gt;
&lt;li&gt;Space Complexity: O(n)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Problems I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;At first I misundertood the question and solved for &apos;return whatever number had atleast k frequency&apos; and thought why tf was this a medium problem.&lt;/li&gt;
&lt;li&gt;Then I realised it was to return the most frequent numbers, and to return the best k among.&lt;/li&gt;
&lt;li&gt;I thought this was simple, but then I found out that you can&apos;t really order a hash map through it&apos;s values. I&apos;d have to find it manually.&lt;/li&gt;
&lt;li&gt;So I found it manually. Looped k times for the requirement, found the maximum value, then located which key had that maximum value, then inserted it into my output and reset its frequency to 0. Of course I had to break this because that loop needed only one maximum not all of them.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be done better&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Using bucket sort, we could store the numbers in buckets of their frequencies. Basically, take a vector where &lt;em&gt;index = frequency&lt;/em&gt; and store the numbers with frequency there in a vector.&lt;/li&gt;
&lt;li&gt;So then each number at say &lt;code&gt;ith&lt;/code&gt; index appears &lt;code&gt;i&lt;/code&gt; times.&lt;/li&gt;
&lt;li&gt;Then we can grab the elements in the descending order, as most frequent ones are at the end of the frequency vector. The moment we have k numbers, we return the solution.&lt;/li&gt;
&lt;li&gt;This solution has O(n) and not O(n2) because even though there is a nested loop, the effective work done is ONCE per number. And at most that can be n.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;int&amp;gt; topKFrequent(vector&amp;lt;int&amp;gt;&amp;amp; nums, int k) {
        int n = nums.size();
        vector&amp;lt;vector&amp;lt;int&amp;gt;&amp;gt; freq(n+1);
        unordered_map&amp;lt;int, int&amp;gt; mapp;
        for (int x : nums){
            mapp[x]++; //store frequencies in hashmap
        }
        for (const auto&amp;amp; [key, value] : mapp){
            freq[value].push_back(key); //create a vector at said frequency&apos;s location and store the number there
        }
        vector&amp;lt;int&amp;gt; output;
        for (int i = n; i &amp;gt; 0; i--){
            if (freq[i].size() != 0){
                for (int j : freq[i]){ //find the numbers and push to output
                    if (output.size()!=k) output.push_back(j);
                    else break;
                }
            }
        }
        return output;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6. Encode and Decode strings&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    char c = &apos;a&apos; - 1;
    string encode(vector&amp;lt;string&amp;gt;&amp;amp; strs) {
        string s = &quot;&quot;; 
        s += c;
        for (const auto&amp;amp; x : strs){
            s += x;
            s += c;
        }
        return s;
    }

    vector&amp;lt;string&amp;gt; decode(string s) {
        vector&amp;lt;string&amp;gt; output;
        if (s == to_string(c)) {
            output.push_back(s);
            return output;
        }
        string temp = &quot;&quot;;
        for (int i = 0; i &amp;lt; s.size(); i++){
            if (s[i] != c){
                temp += s[i];
            }
            else {
                output.push_back(temp);
                temp = &quot;&quot;;
            }
        }
        output.erase(output.begin());
        return output;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problems:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;I knew for a fact that this code was broken. With multiple test cases failing and fixing the test cases only I wasn&apos;t thinking in terms of fixes but &apos;just pass&apos;.&lt;/li&gt;
&lt;li&gt;A fatal flaw in the code is the handling of empty vectors. The encoded string is the delimiter c, and when decoding, we finally pop the first element. This was accidentally working because when an empty string &quot;&quot; was passed it needed to be in the output. But not always.&lt;/li&gt;
&lt;li&gt;In any case, this problem only works on ASCII characters because I used a delimiter not in the ascii range.&lt;/li&gt;
&lt;li&gt;The better solution was to use lengths.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be done better:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;I can encode a word using the lengths of the string, any character as a delimiter, and the word itself.&lt;/li&gt;
&lt;li&gt;Decoding is easy now because I have to look for a number (use string math to convert it to an integer), stop looking when I see a delimiter, then construct the word after iterating through the string for length loops.&lt;/li&gt;
&lt;li&gt;Let&apos;s try it.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:

    string encode(vector&amp;lt;string&amp;gt;&amp;amp; strs) {
        if (strs.empty()) return &quot;&quot;;
        string s;
        for (const auto&amp;amp; x : strs){
            s += to_string(x.size());
            s += &apos;#&apos;;
            s += x;
        }
        return s;
    }

    vector&amp;lt;string&amp;gt; decode(string s) {
        if (s == &quot;&quot;) return {};
        vector&amp;lt;string&amp;gt; output;     
        int i=0;
        while (i&amp;lt;s.size()){
            string len_str=&quot;&quot;;
            int length = 0;
            while (s[i] != &apos;#&apos;){
                len_str += s[i];
                i++;
            }
            length = stoi(len_str);
            string temp = &quot;&quot;;
            i++;
            for (int j=0; j&amp;lt;length; j++){
                temp += s[i];
                i++;
            }
            output.push_back(temp);
        }
        return output;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;There&apos;s definitely a cleaner way to write this.&lt;/li&gt;
&lt;li&gt;We can use two different methods, the latter being more readable while the former is cleaner.&lt;/li&gt;
&lt;li&gt;We could use &lt;code&gt;stoi&lt;/code&gt; function&apos;s property of automatically finding numbers and also reporting how many characters it read. &lt;code&gt;stoi(substr(i), &amp;amp;n)&lt;/code&gt; means: In the substring from index &lt;code&gt;i&lt;/code&gt; till the end, grab the first few numbers and when you find a non-numeric character, stop and report back how many characters you consumed inside &lt;code&gt;n&lt;/code&gt; (which MUST be &lt;code&gt;size_t&lt;/code&gt; and not &lt;code&gt;int&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;OR we could simply use &lt;code&gt;find(&apos;#&apos;, i)&lt;/code&gt; which means return the index where you locate &lt;code&gt;&apos;#&apos;&lt;/code&gt; after &lt;code&gt;i&lt;/code&gt;. So between &lt;code&gt;i&lt;/code&gt; and returned value say &lt;code&gt;j&lt;/code&gt;, is the number, which we can convert to an int using &lt;code&gt;stoi(substr(i, j-i))&lt;/code&gt;. &lt;code&gt;substr(pos, count)&lt;/code&gt; is the syntax.&lt;/li&gt;
&lt;li&gt;Here&apos;s decode in both ways:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;vector&amp;lt;string&amp;gt; decode(string s){
	    if (s==&quot;&quot;) return {};
	    vector&amp;lt;string&amp;gt; output;     
        size_t i=0;
        while (i&amp;lt;s.size()){
            size_t n;
            int length = stoi(s.substr(i), &amp;amp;n);
            i+=n+1;
            output.push_back(s.substr(i, length));
            i+=length;
        }
        return output;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;vector&amp;lt;string&amp;gt; decode(string s){
	    if (s==&quot;&quot;) return {};
	    vector&amp;lt;string&amp;gt; output;     
        size_t i=0;
        while (i&amp;lt;s.size()){
            size_t j = s.find(&apos;#&apos;, i);
            int length = stoi(s.substr(i, j-i));
            i = j+1;
            output.push_back(s.substr(i, length));
            i+=length;
        }
        return output;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;7. Products of Array except self&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;int&amp;gt; productExceptSelf(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        int product = 1;
        int product_wo_zero = 1;
        int zero_counter = 0;
        for (size_t i = 0; i &amp;lt; nums.size(); i++){
            if (nums[i]==0){
                zero_counter++;
            }
            if (zero_counter &amp;lt; 2) {
                if (nums[i] == 0) product *= nums[i];
                else {
                    product *= nums[i];
                    product_wo_zero *= nums[i];
                }
            }
            else {
                vector&amp;lt;int&amp;gt; meow(nums.size(), 0);
                return meow;
            }
        }
        for (int&amp;amp; x : nums){
            if (zero_counter == 0){
                x = product/x;
            }
            else if (zero_counter == 1){
                if (x != 0) x=0;
                else x = product_wo_zero;
            }
        }
        return nums;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;My thinking&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;I knew the naive solution to be grab one element, scroll through the array, and put the values in a different vector, then return it. This was clearly O(n2), so I didn&apos;t go for it.&lt;/li&gt;
&lt;li&gt;Unfortunately, before I could think, the question had a follow up right in the question. &quot;Can you solve it in O(n) without using division approach&quot; and it clicked to me instantly that I could grab the entire product and divide it to each element. So in two passes, one for grabbing the product and another for updating the array, this would be solved.&lt;/li&gt;
&lt;li&gt;Boom, wrote that, then realised that zeroes are a bitch. Not just zero making everything zero, if there was only one zero, it would make every other element zero except itself. So I had to calculate a product_without_zeroes and a product (with zeroes) seperately, then according to the current num I&apos;d replace it with the appropriate value.&lt;/li&gt;
&lt;li&gt;For 2 zeroes and more, the solution is trivial. All zeroes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be made better&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Storing prefix products except current element at the current element, and similarly for postfix products, we can multiply those numbers to get the accurate answer every time.&lt;/li&gt;
&lt;li&gt;Each &lt;code&gt;prefix[i]&lt;/code&gt; holds the product of everything before &lt;code&gt;i&lt;/code&gt;, each &lt;code&gt;postfix[i]&lt;/code&gt; the product of everything after &lt;code&gt;i&lt;/code&gt;, so &lt;code&gt;prefix[i] * postfix[i]&lt;/code&gt; is the product of all elements except &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;int&amp;gt; productExceptSelf(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        vector&amp;lt;int&amp;gt; prefix(nums.size(), 1);
        vector&amp;lt;int&amp;gt; postfix(nums.size(), 1);
        for (size_t i = 1; i &amp;lt; nums.size(); i++){
            prefix[i] = nums[i-1]*prefix[i-1];
        }
        for (int j = nums.size()-2; j &amp;gt;= 0; j--){
            postfix[j] = postfix[j+1]*nums[j+1];
        }
        for (size_t i = 0; i &amp;lt; nums.size(); i++){
            nums[i] = prefix[i]*postfix[i];
        }
        return nums;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;This can also be shortened into only two passes, without any extra space complexity. We basically store the postfix in a variable and update that in each pass over output, which already contains the prefix products after the first &lt;code&gt;for&lt;/code&gt; loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    vector&amp;lt;int&amp;gt; productExceptSelf(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        vector&amp;lt;int&amp;gt; output (nums.size(), 1);
        for (size_t i = 1; i &amp;lt; nums.size(); i++){
            output[i] = nums[i-1]*output[i-1];
        }
        int postfix = 1;
        for (int j = nums.size()-1; j &amp;gt;= 0; j--){
            output[j] *= postfix;
            postfix *= nums[j];
        }
        return output;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;First solution: O(n) time, O(n) extra space (two helper arrays).&lt;/li&gt;
&lt;li&gt;Two-pass solution: O(n) time, O(1) extra space (auxiliary) (only the output, plus one scalar).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;8. Valid Sudoku&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool isValidSudoku(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt;&amp;amp; board) {
        //i = row
        //j = col
        for (int i=0; i &amp;lt; 9; i++){
            unordered_map&amp;lt;int, int&amp;gt; for_row;
            unordered_map&amp;lt;int, int&amp;gt; for_col;
            for (int j=0; j &amp;lt; 9; j++){
                if (board[i][j] != &apos;.&apos;){
                    if (for_row[board[i][j]] &amp;lt; 1) for_row[board[i][j]]++;
                    else return false;
                }   
                if (board[j][i] != &apos;.&apos;){
                    if (for_col[board[j][i]] &amp;lt; 1) for_col[board[j][i]]++;
                    else return false;
                }
            }
        }
        unordered_map&amp;lt;int, unordered_map&amp;lt;int,int&amp;gt;&amp;gt; for_sqr;
        for (int i=0; i &amp;lt; 9; i++){
            for (int j=0; j &amp;lt; 9; j++){
                int current_sqr = (i/3)*3 + (j/3);
                if (board[i][j] != &apos;.&apos;){
                    if (for_sqr[current_sqr][board[i][j]] &amp;lt; 1){
		                for_sqr[current_sqr][board[i][j]]++;
	                } else return false;
                }
            }
        }
        return true;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problems I&apos;ve faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Okay so clearly when I read the question, I was blasted by the size of the sudoku. But I knew how they worked so I did come up with the ideas of checking duplicates in rows and columns each, one pass for each in &lt;code&gt;O(n2)&lt;/code&gt; time. Hash maps!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;O(n2)&lt;/code&gt; is fine actually because the sudoku board is only 9x9 meaning only 81 operations needed.&lt;/li&gt;
&lt;li&gt;The problem was, how do we check the 3x3 squares?? After much thought of &lt;code&gt;for&lt;/code&gt; loops, I realized this needed some trick and not a brute for looping for each 3x3 square in the sudoku board.&lt;/li&gt;
&lt;li&gt;A looked up at a hint in the problem, and it said that I could calculate the index (between 0-8) for each 3x3 square, just by using the row and column value of the current cell. It was &lt;code&gt;(row/3)*3 + (col/3)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;At first I was like, wtf, how could I iterate through?&lt;/li&gt;
&lt;li&gt;But then, why do I have to iterate through? I could create a &lt;code&gt;hash_map&lt;/code&gt; storing a &lt;code&gt;hash_map&lt;/code&gt; connected to that square&apos;s index. This nested &lt;code&gt;hash_map&lt;/code&gt; would be the one checking duplicates.&lt;/li&gt;
&lt;li&gt;But I was unsure if I would be able to code it well so I ended up doing two passes.&lt;/li&gt;
&lt;li&gt;I also realized I had to put the &lt;code&gt;for_row&lt;/code&gt; and &lt;code&gt;for_col&lt;/code&gt; in the outer loop instead of the inner loop because it forgot at every cell lmfao.&lt;/li&gt;
&lt;li&gt;Of course, I had early returning the moment a number went above one.&lt;/li&gt;
&lt;li&gt;Oh! I had to change the condition of the duplicate from &lt;code&gt;&amp;lt;2&lt;/code&gt; to &lt;code&gt;&amp;lt;1&lt;/code&gt; because &lt;code&gt;map[val]&lt;/code&gt; creates it in the hash map, and if a duplicate is seen it will push the value from 0 to 1 directly. The moment a duplicate is seen, &lt;code&gt;&amp;lt;1&lt;/code&gt; is false so it returns early.&lt;/li&gt;
&lt;li&gt;Now I&apos;ll put the square pass in the main loop so there&apos;s just ONE pass.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool isValidSudoku(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt;&amp;amp; board) {
        //i = row
        //j = col
        unordered_map&amp;lt;int, unordered_map&amp;lt;int,int&amp;gt;&amp;gt; for_sqr;
        for (int i=0; i &amp;lt; 9; i++){
            unordered_map&amp;lt;int, int&amp;gt; for_row;
            unordered_map&amp;lt;int, int&amp;gt; for_col;
            for (int j=0; j &amp;lt; 9; j++){
                if (board[i][j] != &apos;.&apos;){
                    if (for_row[board[i][j]] &amp;lt; 1) for_row[board[i][j]]++;
                    else return false;
                }
                if (board[j][i] != &apos;.&apos;){
                    if (for_col[board[j][i]] &amp;lt; 1) for_col[board[j][i]]++;
                    else return false;
                }
                int current_sqr = (i/3)*3 + (j/3);
                if (board[i][j] != &apos;.&apos;){
                    if (for_sqr[current_sqr][board[i][j]] &amp;lt; 1) {
	                    for_sqr[current_sqr][board[i][j]]++;
	                }
                    else return false;
                }
            }
        }
        return true;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;What can be done better?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Hashmaps are cool. But you know what&apos;s cooler? Arrays. We can access elements in literally &lt;code&gt;O(1)&lt;/code&gt; time.&lt;/li&gt;
&lt;li&gt;Similar to storing &lt;code&gt;freq[26]&lt;/code&gt; when testing anagrams, we know that the numbers in the sudoku table are between 1-9 and rows, columns, and 3x3 squares are also from 0-8 (index).&lt;/li&gt;
&lt;li&gt;So we could store 3 matrices:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;row_count[row r][what number we looking at, n]&lt;/code&gt; which tells the number of times a number n was seen in row r.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;col_count[col c][what number we looking at, n]&lt;/code&gt; which tells the number of times a number n was seen in col c;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sqr_count[sqr s][what number we looking at n&lt;/code&gt; which tells the number of times a number n was seen in sqr s.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;r, c, s&lt;/code&gt; all range from &lt;code&gt;0-8&lt;/code&gt;, and the number &lt;code&gt;n&lt;/code&gt; itself too.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Let&apos;s code it!&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    bool isValidSudoku(vector&amp;lt;vector&amp;lt;char&amp;gt;&amp;gt;&amp;amp; board) {
        //i = row
        //j = col
        int sqr_c[9][9] = {0};
        int row_c[9][9] = {0};
        int col_c[9][9] = {0};
        for (int i=0; i &amp;lt; 9; i++){
            for (int j=0; j &amp;lt; 9; j++){
                if (board[i][j]==&apos;.&apos;) continue;
                
                if (row_c[i][board[i][j]-&apos;1&apos;]==0) row_c[i][board[i][j]-&apos;1&apos;]++;
                else return false;

                if (col_c[j][board[i][j]-&apos;1&apos;]==0) col_c[j][board[i][j]-&apos;1&apos;]++;
                else return false;

                if (sqr_c[(i/3)*3+(j/3);][board[i][j]-&apos;1&apos;]==0) sqr_c[s][board[i][j]-&apos;1&apos;]++;
                else return false;
            }
        }
        return true;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;9. Longest Consecutive Sequence&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    int longestConsecutive(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        
        vector&amp;lt;int&amp;gt; counts;
        unordered_map&amp;lt;int, int&amp;gt; mapp;
        for (size_t i = 0; i &amp;lt; nums.size(); i++){
            mapp[nums[i]] = i;
        }
        int count = 0;
        
        for (int x : nums){
            if (mapp.find(x-1)==mapp.end()){
                count++;
                while (mapp.find(x+1) != mapp.end()){
                    count++;
                    x = x+1;
                }
                counts.push_back(count);
                count=0;
            }
        }

        int maxi = 0;
        for (int x : counts){
            maxi = max(x, maxi);
        }
        return maxi;
    }
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Problems I faced&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Upon seeing the requirement of the solution in O(n) and the obvious solution that came to mind was O(n2), I didn&apos;t want to use nested loops.&lt;/li&gt;
&lt;li&gt;So? I tried to go for one &lt;code&gt;for&lt;/code&gt; loop where I would change the index based on what next element I found.&lt;/li&gt;
&lt;li&gt;After writing it&apos;s code, I realized that messing with indexes in &lt;code&gt;for&lt;/code&gt; loops is almost ALWAYS bound for error. Because the condition that leaves the &lt;code&gt;for&lt;/code&gt; loop is never coded inside the for loop manually (like in &lt;code&gt;while&lt;/code&gt;) but is &lt;em&gt;included&lt;/em&gt; in the &lt;code&gt;for&lt;/code&gt; loop.&lt;/li&gt;
&lt;li&gt;Clearly, my solution was failing due to forever looping and reaching TLE.&lt;/li&gt;
&lt;li&gt;First example should have passed on my code &lt;code&gt;[2,20,4,10,3,4,5]&lt;/code&gt; because when we reached the final element &lt;code&gt;5&lt;/code&gt; i++ would have escaped the for loop. YET somehow my count value kept being 0 for some reason.&lt;/li&gt;
&lt;li&gt;Knowing well this wasn&apos;t going to work, I looked up whether this problem with a nested loop would truly be O(n2) or not.&lt;/li&gt;
&lt;li&gt;I was looking for the worst case, something like &lt;code&gt;[1, 3, 5, 7]&lt;/code&gt; or &lt;code&gt;[1,2,4,5,7,8]&lt;/code&gt; and was thinking that this would for &lt;code&gt;n*n/2&lt;/code&gt; times. But reimagining it by writing it down, we ONLY get in the loop for specific elements, and run the nested loop ONCE for each number. Meaning each number is visited only ONCE. aka, O(n).&lt;/li&gt;
&lt;li&gt;Coded it, got it running.&lt;/li&gt;
&lt;li&gt;Didn&apos;t face syntax issues much this time.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Why it works?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;This solution is O(n) in both time and space, because the extra set we created consumes the space as n grows. Time because each element is visited once. But why?&lt;/li&gt;
&lt;li&gt;You see, we only start checking the consecutive-ness of elements IF we know that they are the start of that sequence. We check that by trying to find the number &lt;em&gt;before&lt;/em&gt; the element and if there&apos;s none, it would be the first of its possible list.&lt;/li&gt;
&lt;li&gt;Then we use the while loop to visit the elements of its consecutive list.&lt;/li&gt;
&lt;li&gt;Then the outer loops moves forward, but doesn&apos;t initiate the inner loop since the consecutive elements (that aren&apos;t the first element) will not be considered as a new list to discover. They only get visited because they had a first element before them.&lt;/li&gt;
&lt;li&gt;So assuming there are &lt;code&gt;n&lt;/code&gt; elements in &lt;code&gt;nums&lt;/code&gt;, then the outer loop does run &lt;code&gt;n&lt;/code&gt; times. But the inner loop only runs when we find a &lt;em&gt;first&lt;/em&gt; element, which reads the next say &lt;code&gt;y&lt;/code&gt; consecutive elements (y operations). So each &lt;em&gt;first&lt;/em&gt; element starts &lt;code&gt;y&lt;/code&gt; operations. The &lt;em&gt;middle&lt;/em&gt; elements don&apos;t, so only 1 operation for them (the outer loop). We only start looking for middle elements AFTER a first element existed. MEANING we only do &lt;code&gt;n&lt;/code&gt; operations + &lt;code&gt;at most n&lt;/code&gt; operations for each first element we found. This isn&apos;t &lt;code&gt;n*(at most n)&lt;/code&gt; but &lt;code&gt;n+ (at most n)&lt;/code&gt; which is basically, O(n).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Every element is walked by an inner while loop &lt;strong&gt;at most&lt;/strong&gt; once, ever, across the entire run.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Because each number belongs to exactly one consecutive sequence, and that sequence is walked exactly once, from its unique start.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;What can be made better?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Instead of saving it in a hash_map (which stored the index earlier and was useless here because we only want validity of presence of a number) we can store it in an unordered_set. We still have O(1) lookups, and no duplicates.&lt;/li&gt;
&lt;li&gt;Directly copy elements by using the syntax &lt;code&gt;unordered_set&amp;lt;int&amp;gt; mapp(nums.begin(), nums.end())&lt;/code&gt; man these hacks are nuts. This is same as a &lt;code&gt;for&lt;/code&gt; loop (O(n)) but saves me from writing a for loop.&lt;/li&gt;
&lt;li&gt;Anyways, instead of saving things in a vector, we can update a variable of best_count and return that. Saves space complexity and an extra &lt;code&gt;for&lt;/code&gt; loop.&lt;/li&gt;
&lt;li&gt;Here&apos;s the final code:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;class Solution {
public:
    int longestConsecutive(vector&amp;lt;int&amp;gt;&amp;amp; nums) {
        
        unordered_set&amp;lt;int&amp;gt; mapp(nums.begin(), nums.end());
        int best_count = 0;
        
        for (int x : mapp){
            if (mapp.find(x-1)==mapp.end()){
                int count=1;
                int curr = x;
                while (mapp.find(curr+1) != mapp.end()){
                    count++;
                    curr = curr+1;
                }
                best_count=max(best_count, count);
            }
        }

        return best_count;

    }
};
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><category>C++</category><category>DSA</category><category>Neetcode</category></item></channel></rss>