《程序员面试金典(第6版)》面试题 05.03. 翻转数位(贪心算法思想,C++)

本文介绍了如何通过位运算解决寻找32位整数中能通过改变一个0得到的最长连续1的问题。文中提供了两种方法,一是暴力破解,利用双层循环检查每一位,二是使用贪心算法,每次遇到0更新状态,遇到1则增加计数。文章强调了贪心算法在解决此类问题上的高效性。
摘要由CSDN通过智能技术生成

题目描述

给定一个32位整数 num,你可以将一个数位从0变为1。请编写一个程序,找出你能够获得的最长的一串1的长度。

示例 1:

  • 输入: num = 1775(110111011112)
    输出: 8

示例 2:

  • 输入: num = 7(01112)
    输出: 4

解题思路与代码

这道题的解法涉及到位运算,如果对位运算不太了解的话,请看我这篇文章扫除盲点:教你理解位运算符

方法一: 暴力破解

暴力破解是指我们使用双层for循环去解题。

我们第一层for循环去判断num的每一位是否为1,1有1的逻辑,0有0的逻辑。
第二层for循环就是去记录从1开始的,连续为1的数量。

这种方式的缺点在于,中间的逻辑很有可能会写错,反复检查会很麻烦。

具体实现看代码:

class Solution {
public:
    int reverseBits(int num) {
        bool flag = true; //标准位,类似与开关,第一次出现0,变成false,第二次出现0,变成true
        int maxLength = 0; //记录最大长度
        int count = 0;//记录1的数量

        for(int i = 0; i < 32; ++i){
            bool bit = num & (1<<i);
            cout<<bit<<",";
            if(bit == 1){//为1的逻辑
                flag = true;
                count = 0;
                for(int j = i; j < 32; ++j){
                    bool bit_2 = num & (1<<j);
                    if(bit_2 && flag){
                        count+=1;
                        if(count > maxLength) maxLength = count;
                    }else if(bit_2 == 0 && flag){
                        count += 1;
                        if(count > maxLength) maxLength = count;
                        flag = false;
                    }else if(bit_2 == 1 && !flag){
                        count += 1;
                        if(count > maxLength) maxLength = count;
                    }else break;
                }
            }
            if(bit == 0){
                num |= (1<<i);
                count = 0;
                for(int j = i; j < 32; ++j){
                    bool bit_2 = num & (1<<j);
                    if(bit_2 == 1 ){
                        count += 1;
                        if(count > maxLength) maxLength = count;
                    }else if(bit_2 == 0){
                        num &= ~(1<<i);
                        break;
                    }
                }
            }
        }
        return maxLength;
    }
};

在这里插入图片描述

复杂度分析

时间复杂度:O(n!) ,n第一开始是32,然后会随着i的增大而减小。
空间复杂度:O(1),我们没有申请额外的数据结构去存储数据。

方法二:使用贪心算法的思想去解题

贪心算法的思想是每一步选择当前状态下最优的决策,并不考虑之后的结果,以期达到全局最优解的算法思想。

在这道题中我们一共要设置三个变量,small,big,maxLength。
当遇到0时,big 会等于 small 之前的状态 + 1,然后small会将自己置为0。
当遇到1时,big和small都会加1。
maxLength会不断比较自己与big的大小,并永远保持自己是最大的。最后返回maxLength。

具体代码如下:

class Solution {
public:
    int reverseBits(int num) {
        int small = 0; int big = 0; int maxLength = 0;
        for(int i = 0; i < 32; ++i){
            if(num & (1<<i) ){ //判断这一位是否为0
                ++small;
                ++big;
            }else{
                big = small + 1;
                small = 0;
            }
            maxLength = max(big,maxLength);
        }
        return maxLength;
    }
};

总结

这道题对我来说,确实也不算是一道难题,但也没那么简单。如果我会贪心思想了话,这道题或许会更加的简单。后序,我会更新双指针与动态规划的做法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿宋同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值