1. 程式人生 > >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 <= 109
在小於等於n的數中,找到所有滿足相鄰的bit位不同時為1的數.

這個可以對數字的最高位進行討論:假設n的最高位在K
1. 找最高位也是K的無”11”數
2. 找最高位小於K的無”11”數

兩部分加起來就是我們要的結果.

就最高位小於K的時候, 這個就比較好算了. 因為這些數一定是小於n的.
記最高位1 為 i 的無”11”數有 a[i] 種,

101xxx
1001xx
10001x
100001
100000

a[i] = a[i-2]+a[i-3] + … + a[0]

可進一步推得a[i] = a[i-1]+a[i-2].

對於最高位為K的數就比較麻煩了, 因為有小於等於n的限制在這.
遍歷n的bit位, 從高到低. 如果遇到一個bit為1, 我們就把這位設為0, 剩下低位的部分就可以用上面a[i]來填補了.

1001001
1000xxx 
    剩下的這3個bitsa[3], a[2], a[1],a[0]對應的那些數來填補就可以了.

a還有一種特殊情況: n中包含”11”. 這樣n這個數就不能算進去了. 而且在遇到最高的”11”的時候, 我們需要把它變為”10”, 或”01”.

1011010101
100xxxxxxx 剩下的7位用a[7],a[6], ..a[0]對應的數填補
1010xxxxxx 剩下的6位用a[6],a[5], ... a[0]對應的數來填補

為了計算方便, 我們可以先計算sum[i] = a[i] + a[i-1] + … + a[0]

class Solution {
public:

    /** 
     * @brief 找到二進位制中最高位的"11"
     * 
     * @param num
     * 
     * @return 返回最高位"11"所在的位置
     */
    int find_dual1(const int num) {
        int mask = (1<<1) + 1 ;
        int b = -1;
        for(int i = 1; i <= 30; ++i) {
            if((num&mask) == mask){
                b = i;
            }
            mask <<=1;
        }
        return b;
    }

    int find_int(const int num, const int b, const vector<int> & sum) {

        int cnt = 0;
        /*最高位等於b的數*/
        int dual1_pos = find_dual1(num);
        if(-1 == dual1_pos) {
            cnt += 1;/*num self.*/
        }
        int next_b = b-1;
        for(; next_b > dual1_pos; --next_b) {
            if(num & (1 << next_b)) {
                cnt += sum[next_b];
            }
        }
        if(-1 != dual1_pos){
            if(dual1_pos == b) {
                cnt += sum[dual1_pos-1];
            }else {
                cnt += sum[dual1_pos];
                cnt += sum[dual1_pos-1];
            }
        }

        /*最高位小於b的數*/
        cnt += sum[b];
        return cnt;
    }

    int findIntegers(int num) {
        int b = 0; 
        while(1<<(b+1) <= num) {
            ++b;
        }

        vector<int> a(b+1, 0);
        a[0] = 1;
        a[1] = 1;
        a[2] = 1;
        for(int i = 3; i <= b; ++i) {
            a[i] = a[i-1] + a[i-2];
        }
        vector<int> sum(b+1,0);
        int s = 0;
        for(int i = 0; i <= b; ++i) {
            s += a[i];
            sum[i] = s;
        }

        return find_int(num, b, sum);
    }
};