1. 程式人生 > >Leetcode 600. Non-negative Integers without Consecutive Ones

Leetcode 600. Non-negative Integers without Consecutive Ones

Leetcode 600. Non-negative Integers without Consecutive Ones

題目:

Given a positive integer n, find the number of non-negative integers less than or equal to n, whose binary representations do NOT contain consecutive ones.

Example 1:

Input: 5
Output: 5
Explanation: 
Here are the non-negative integers <= 5 with their corresponding binary representations:
0 : 0
1 : 1
2 : 10
3 : 11
4 : 100
5 : 101
Among them, only integer 3 disobeys the rule (two consecutive ones) and the other 5 satisfy the rule. 

Note: 1 <= n <= 10^9

解法:

先理解一下題意:大概意思是說找一下小於等於 N 的數裡面有多少個數表示成二進位制形式之後,不會有連續的兩個 1 出現在其二進位制序列裡面。

先說一下我最開始的想法:

從 0 到 N 遍歷 N 個數字,將小於等於 N 的每一個數字用bitset表示出來,然後用一個迴圈從bitset的0位置開始將相鄰兩位相加,觀察結果是否會有 2 出現,如果出現就證明不滿足題意;如果遍歷完沒出現,就讓統計值 +1 ;

這種方法是可以求出最終結果的,但是會超時!所以直觀的方法行不通!

如圖:

在這裡插入圖片描述


另尋他路

在網上檢視大佬們的解題思路,有一種比較巧妙的方法介紹一下:

在這裡插入圖片描述

最後我們所要求的結果是:

total = a[i-1] + b[i-1]( i 在這裡指數字轉二進位制後的長度)

但是我們使用的這種方法會有多算的情況,比如當我們輸入 8 或 9 時候,其二進位制長度都是 4 ,所以我們在計算小於等於 8 的滿足題意的數字的時候,可能會把 9 10 都算進去,所以我們要把多餘的情況減掉。

那具體應該怎麼減去這些數字?

假如我們要計算 num = 8 的情況,那麼當長度等於 4 時候,則 0、1、2、4、5、8共 6 個數字滿足題意,但是total = a[3]+b[3] = 8 ,多餘的情況為 9 = 1001(2) 、10 = 1010(2) ;

我們演算法最初開始在生成二進位制數字時候,是逆序生成的,也即 8 = 0001 ,所以我們可以從待測序列的倒數第二位往前算

  • 如果位置 j 和位置 j+1 上的數字都是 0 ,那麼就在 total中減去 b[j]
  • 如果位置 j 和位置 j+1 上的數字都是 1 ,那麼直接退出

這裡之所以減去 b[j],因為在位置j上可能會出現滿足題設要求的 1 ,而在 1 位置上滿足情況的個數為 b[j]

程式碼:

class Solution 
{
public:
    int findIntegers(int num)
    {
        int n = num;
        string t = "";
        while (n > 0)
        {
            t += (n & 1) == 1 ? "1" : "0";
            n = n >> 1;
        }

        vector<int> zero(t.length() , 0), one(t.length(), 0);
        zero[0] = one[0] = 1;
        for (int i = 1; i < t.length(); i++)
        {
            zero[i] = zero[i - 1] + one[i -1];
            one[i] = zero[i - 1];
        }

        int res = zero[t.length() - 1] + one[t.length() - 1];
        for (int i = t.length() - 2; i >= 0; i--)
        {
            if (t[i] == '1' && t[i + 1] == '1')
                break;
            if (t[i] == '0' && t[i + 1] == '0')
                res -= one[i];
        }
        return res;
    }
};