Challenge #18 - Count Negative Numbers in a Sorted Matrix
Tags: programming, javascript, codenewbie, leetcode
Published: 2021-10-06 06:13:44

Hey-yo!

Welcome to day #18 of [my coding diary](https://www.pankajtanwar.in//coding-diary). It has been a great journey so far, a really good daily-code-workout. It's too much fun, trust me.

### TLDR;

- Problem seemed pretty easy to me at first but it turned out be a gem when I tried to optimize the solution. 
- This is one of the cleverest problems I have ever seen.
- One can just slap on the brute force approach and get on with his life BUT I would recommend everyone to just solve this problem once.

<hr/>

**Problem of the day** - [Count Negative Numbers in a Sorted Matrix](https://leetcode.com/problems/count-negative-numbers-in-a-sorted-matrix/)

**Tag** - Easy

Given a `m x n` matrix `grid` which is sorted in non-increasing order both row-wise and column-wise, return _the number of **negative** numbers in_ `grid`.

**Example 1:**

**Input:** grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]
**Output:** 8
**Explanation:** There are 8 negatives number in the matrix.

<hr/>

Ahhmmm, calm down, calm down! I know this seems pretty easy. I could not stop my hands, coding the brute force `O(n2)`solution for it.

```cpp
class Solution {
public:
    int countNegatives(vector<vector<int>>& grid) {
        int res = 0;
        for(auto row: grid) {
            for(int val: row) {
                if(val < 0) res++;
            }
        }
        return res;
    }
};
```

Quite straightforward. 30 seconds of code! haha. But pretty bad from an optimization point of view. Let's think of a good approach.

<hr/>

When I see something sorted, I call my dearest friend, `binary search`. Let's reduce the time complexity from `O(n2)` to `O(n log m)`. 

**Here is the code**

```cpp
class Solution {
public:
    int getIndex(vector<int> row) {
        int low = 0;
        int high = row.size() - 1;
        int mid = (low+high)/2;
        
        while(low != high) {
            mid = (low+high)/2;
            if(row[mid] >= 0) {
                low = mid +1; 
            } else {
                high = mid;
            }
        }
        return row[low] >= 0 ? -1 : low;
    }
    
    int countNegatives(vector<vector<int>>& grid) {
        int res = 0;
        int index;
        for(auto row: grid) {
            index = getIndex(row);
            res += (index == -1 ? 0 : row.size() - index);
        }
        return res;
    }
};
```

Pardon my ugly code style. 

I hit submit and was about to celebrate my small achievement BUT a small text below the problem statement shattered all my hopes.

> **Follow up:** Could you find an `O(n + m)` solution?

Oh man, I thought I cracked the best solution for this. Ah shit, here we go again.

<hr/>

No worries, let's try to find it can be done in `O(n + m)`. 

I am not gonna lie. I tried my best but could not find any approach to solving it in the given time complexity. I can just think of something, checking for negative element, if found, based on that, just tick mark the index for new rows also. 

After checking out the discussion tab, I was blown away by the approach. It was so clever. 

So, We start from the upper right, check if one positive element is found, we just jump to the next row, for the same index (as we know columns are also in a sorted manner). 

I know, it's complex to understand. This guy has written [an excellent explanation](https://leetcode.com/problems/count-negative-numbers-in-a-sorted-matrix/discuss/510217/C%2B%2B-Three-Methods). Check it out.

**Here is the smartest approach**

```cpp
class Solution {
public:
    int countNegatives(vector<vector<int>>& grid) {
        int res = 0;
        
        int row = grid.size();
        int col = grid[0].size();
        int r = 0;
        int n = col - 1;
        
        while(r < row) {
            while(n >= 0 && grid[r][n] < 0) n--;
            res += col - n - 1;
            r++;
        }
        return res;
    }
};
```

I am in love with this problem. The way, it's designed is commendable. It was fun solving it.

As always, if you have any thoughts about anything shared above, don't hesitate to [reach out](https://twitter.com/the2ndfloorguy).

> Do let me know if you are also solving problems. 

<hr/>

You might like previous editions of [my coding diary](/coding-diary)

- [Day #17 - Sum of Unique Elements.](https://www.pankajtanwar.in//code/sum-of-unique-elements/)
- [Day #16 - Best Time to Buy and Sell Stock.](https://pankajtanwar.in/code/best-time-to-buy-and-sell-stock/)
- [Day #15 - Count Number of Pairs With Absolute Difference K.](https://pankajtanwar.in/code/count-number-of-pairs-with-absolute-difference-k/)
- [Day #14 - Minimum Number of Operations to Move All Balls to Each Box.](https://pankajtanwar.in/code/minimum-number-of-operations-to-move-all-balls-to-each-box/)
- [Day #13 - Number Of Rectangles That Can Form The Largest Square.](https://www.pankajtanwar.in//code/number-of-rectangles-that-can-form-the-largest-square/)
- [Day #12 - Unique Morse Code Words.](https://www.pankajtanwar.in//code/unique-morse-code-words/)
- [Day #11 - Count the Number of Consistent Strings.](https://www.pankajtanwar.in//code/count-the-number-of-consistent-strings/)
- [Day #10 - Find Greatest Common Divisor of Array.](https://www.pankajtanwar.in//code/find-greatest-common-divisor-of-array/)