题目难度: 简单
前几天的题目难度有点大, 那今天我们就来做一道简单题吧 😝 这道题比较简单, 但也有多种解法, 而且如果加上一些进阶限制条件, 比如单次遍历和 O(1)空间之类的, 也值得思考一下如何进行优化
题目描述
给定一个 32 位整数 num,你可以将一个数位从 0 变为 1。请编写一个程序,找出你能够获得的最长的一串 1 的长度。
题目样例
示例 1
输入
num = 1775(0b11011101111)
输出
8
解释
把最后面的那个 0 换成 1 就能得到连续 8 个 1 了
示例 2
输入
num = 7(0b0111)
输出
4
解释
把最左边的 0 换成 1
题目思考
- 根据题目描述, 有没有什么简单直接的思路?
- 如何优化, 能够动态地一次遍历就得到结果, 从而满足进阶限制条件呢?
解决方案
方案 1
思路
- 最直接的方法, 既然要求翻转后的最长长度, 那是不是可以针对每一位 0, 将其变成 1 后统计新数字的最长连续 1 长度, 看看哪个最长即可
- 注意不要忘了求原来数字的最长长度, 因为题目说的是可以翻转, 意思就是不翻转也行
复杂度
- 时间复杂度 O(32*32): 总共需要判断 32 位中每一位的 0 翻转后的数字(最差情况), 每次判断需要遍历所有 32 位数, 所以是 O(32*32)
- 空间复杂度 O(1): 只使用了几个变量
代码
Python 3
class Solution: def reverseBits(self, num: int) -> int: def getLongest1(n): res = 0 curcnt = 0 for i in range(32): if n & 1 << i: # 当前位是1, 连续长度curcnt+1 curcnt += 1 res = max(res, curcnt) else: # 当前位是0, 中断了连续1, curcnt重置为0 curcnt = 0 return res res = getLongest1(num) for i in range(32): if num & (1 << i) == 0: # 将第i位的0翻转为1后计算新的数字的最大连续1的长度 res = max(res, getLongest1(num | (1 << i))) return res
C++
class Solution { public: int reverseBits(int num) { auto getLongest1 = [](int n) { int res = 0; int curcnt = 0; for(int i = 0; i < 32; ++i) { if (n & (1 << i)) { res = max(res, ++curcnt); } else { curcnt = 0; } } return res; }; int res = getLongest1(num); for (int i = 0; i < 32; ++i) { if ((num & (1 << i)) == 0) { res = max(res, getLongest1(num | (1 << i))); } } return res; } };
方案 2
思路
- 回顾方案 1, 对于每一位的 0 都需要翻转下然后统计新的数字的连续 1 长度, 这个工作是否可以通过一次遍历就完成?
- 因为中间可能存在翻转, 所以需要记录上一个连续 1 和当前的连续 1 的长度, 自然就想到了双指针
- 具体做法如下:
- 使用两个变量 pre 和 cur
- pre 表示上一个连续 1 的长度, 初始化为 0
- cur 表示当前连续 1 的长度, 初始化为 0
- 结果即为最大的 pre+1+cur (1 表示中间从 0 翻转成的那个 1)
- 需要注意 32 位全为 1 (即-1)的特殊情况, 这个时候 cur 是 32, pre 是 0, pre+1+cur 就不对了, 所以最终结果 res 需要为 min(32, res)
复杂度
- 时间复杂度 O(32): 只需要遍历一遍每一位即可
- 空间复杂度 O(1): 只使用了几个变量
代码
Python 3
class Solution: def reverseBits(self, num: int) -> int: pre, cur = 0, 0 # 结果至少为1, 因为即使全为0, 也可以翻转其中一位变成1个1 res = 1 for i in range(32): if num & (1 << i): # 当前位是1, 增加cur的长度, 同时更新结果值 cur += 1 res = max(res, pre + cur + 1) else: # 当前位是0, 不能继续连续下去了, 更新pre和cur pre = cur cur = 0 return min(32, res)
C++
class Solution { public: int reverseBits(int num) { int res = 1; int pre = 0, cur = 0; for (int i = 0; i < 32; ++i) { if (num & (1 << i)) { ++cur; res = max(res, pre + cur + 1); } else { pre = cur; cur = 0; } } return min(res, 32); } };
大家可以在下面这些地方找到我~😊
我的公众号: 每日精选算法题, 欢迎大家扫码关注~😊