程序员面试金典 5.3

Flip Bit to Win:将一个整数中的某一比特位置位,输入该整数的二进制表示中最长的比特位为1的长度。

可以把int转换为01序列长度的表示方式,然后依次尝试将0序列中最左或者最右的0置位,并和左右两部分的1序列合并,最终找出最大值,算法的时间复杂度为O(b),空间复杂度也为O(b),其中b表示输入数据以比特位表示的长度,也可以视为O(1)

class Solution {
public:
    int reverseBits(int num) {
        calSeqLength(num);
        int ret = 0;
        for(size_t i = 0; i < vecSeqLen.size(); i += 2)
        {
            int left = i >= 1 ? vecSeqLen[i - 1] : 0;
            int right = i + 1 < vecSeqLen.size() ? vecSeqLen[i + 1] : 0;
            int total;
            if(vecSeqLen[i] == 1) total = left + right + 1;
            else {
                if(left > right) total = left + 1;
                else total = right + 1;
            }
            if(total > ret) ret = total;
        }
        return ret;
    }
private:
    vector<int> vecSeqLen;
    void calSeqLength(int num)
    {   
        bool bSearch = false;
        int cnt = 0;
        for(int idx = 0; idx < sizeof(decltype(num)) * 8; idx++)
        {
            if((num & 0x1) != bSearch){
                vecSeqLen.push_back(cnt);
                bSearch = !bSearch;
                cnt = 0;
            }
            cnt++;
            num >>= 1;
        }
        vecSeqLen.push_back(cnt);
    }
};

可以优化一下,把空间复杂度降低为纯O(1)的,从右向左扫描每一位,使用curr记录当前1序列的长度,prev记录紧邻当前序列右侧第101序列长度。curr + 1 + prev可以表示翻转currprev之间的0,但是不存在prev序列时,curr + 1 + prev可以表示翻转curr位置上的0,因此两种情况的代码是一致的。

class Solution {
public:
    int reverseBits(int num) {
        if(num == INT_MAX) return sizeof(decltype(num)) * 8;
        int curr = 0, prev = 0;
        int ret = 0;
        while(num != 0){
            if((num & 0x1) == 1) curr++;
            else{
                if(ret < curr + 1 + prev) ret = curr + 1 + prev;
                prev = curr;
                curr = 0;
            }
            num >>= 1;
        }
        if(ret < curr + 1 + prev) ret = curr + 1 + prev;
        return ret;
    }
};
发布了194 篇原创文章 · 获赞 2 · 访问量 7726

猜你喜欢

转载自blog.csdn.net/RayoNicks/article/details/105383954
今日推荐