Leetcode.com problem: "Non-Negative Integers Without Consecutive Ones"

James S. Plank

Sat May 28 04:15:42 PM EDT 2022

In cast Leetcode's servers are down

You have a procedure that takes an int and returns an int. Suppose the input is n. Count how many integers there are that are ≥ 0 and ≤ n and do not have two consecutive one bits in their binary representations. Max n is 109.


Examples

n    answer
0   |   1
1   |   2
2   |   3
3   |   3
4   |   4
5   |   5
6   |   5
7   |   5
8   |   6
9   |   7

Hints

I did this one twice. My first solution was plenty fast, but pretty slow in leetcode land (only faster than 5%). So I did a second, faster solution. I'll talk about both.

Solution 0 -- Enumerate, so you have correct solutions

That was my first solution. I knew it would be too slow, but it gave me answers for my other solutions. Here you go -- cut and paste it if you want to test yourself:
int dumb(int n)
{
  bool last;
  int i, j, ans;

  printf("dumb(%d)\n", n);
  ans = 0;
  for (i = 0; i <= n; i++) {
    last = false;
    for (j = i; j > 0; j>>=1) {
      if (j&1) {
        if (last) {
          j = -1;
        } else {
          last = true;
        }
      } else last = false;
    }
    if (j == 0) ans++;
  }
  return ans;
}

Solution 1 -- Dynamic programming

If you know me at all, you know that I don't try to be too clever math-wise to solve problems like this. So I don't even bother with trying for a closed-form solution. Instead, I go straight to dynamic programming. The key here is to spot the recursion. Here's what I did: Code it up and memoize and you're done. The cache is really small (under 100 when n is 9 decimal digits).

Solution 2 -- Making it faster and removing recursion

To make it faster, I pretty much made use of the same observations, but took them a step further. Let a(n) be the answer for n.

This took my solution from 30ms to 7ms. That was still slow compared to other solutions, but I don't really care at this point. It's fast enough for me to go on with the rest of my day...