位操作算法解析:获取相邻数值的二进制挑战

位操作算法解析:获取相邻数值的二进制挑战

interactive-coding-challenges 120+ interactive Python coding interview challenges (algorithms and data structures). Includes Anki flashcards. interactive-coding-challenges 项目地址: https://gitcode.com/gh_mirrors/in/interactive-coding-challenges

问题描述

给定一个正整数,找出与该数具有相同数量1的二进制表示的下一个最大数和下一个最小数。这个问题考察了我们对二进制位操作的理解和运用能力。

约束条件

  • 输出必须为正整数
  • 输入可能无效,需要进行验证
  • 假设内存足够存放处理结果

测试用例

  • 无效输入测试:
    • None -> 抛出异常
    • 0 -> 抛出异常
    • 负数 -> 抛出异常
  • 常规测试:
    • 输入:0000 0000 1101 0111
    • 下一个最大数:0000 0000 1101 1011
    • 下一个最小数:0000 0000 1100 1111

算法原理

获取下一个最大数

  1. 寻找关键位:找到最右边的非拖尾0位(即该0位右边至少有一个1)

    • 从右向左扫描,统计连续的0的数量
    • 接着统计连续的1的数量
    • 关键位的位置 = 连续0的数量 + 连续1的数量
  2. 设置关键位:将关键位设置为1

  3. 清理右侧位:将关键位右侧的所有位清零

  4. 重新设置1位:在最低位开始,设置(连续1的数量-1)个1

获取下一个最小数

  1. 寻找关键位:找到最右边的非拖尾1位(即该1位右边至少有一个0)

    • 从右向左扫描,统计连续的1的数量
    • 接着统计连续的0的数量
    • 关键位的位置 = 连续1的数量 + 连续0的数量
  2. 清除关键位:将关键位设置为0

  3. 清理右侧位:将关键位右侧的所有位清零

  4. 重新设置1位:在最低位开始,设置(连续1的数量+1)个1

复杂度分析

  • 时间复杂度:O(b),其中b是数字的二进制位数
  • 空间复杂度:O(b),其中b是数字的二进制位数

代码实现

class Bits(object):

    def get_next_largest(self, num):
        if num is None:
            raise TypeError('num cannot be None')
        if num <= 0:
            raise ValueError('num cannot be 0 or negative')
        num_ones = 0
        num_zeroes = 0
        num_copy = num
        # 寻找最右边的非拖尾0位
        # 统计右边的连续0数量
        while num_copy != 0 and num_copy & 1 == 0:
            num_zeroes += 1
            num_copy >>= 1
        # 统计右边的连续1数量
        while num_copy != 0 and num_copy & 1 == 1:
            num_ones += 1
            num_copy >>= 1
        # 确定关键位位置并设置该位
        index = num_zeroes + num_ones
        num |= 1 << index
        # 清除关键位右侧的所有位
        num &= ~((1 << index) - 1)
        # 从最低位开始设置1
        num |= ((1 << num_ones - 1) - 1)
        return num

    def get_next_smallest(self, num):
        if num is None:
            raise TypeError('num cannot be None')
        if num <= 0:
            raise ValueError('num cannot be 0 or negative')
        num_ones = 0
        num_zeroes = 0
        num_copy = num
        # 寻找最右边的非拖尾1位
        # 统计右边的连续1数量
        while num_copy != 0 and num_copy & 1 == 1:
            num_ones += 1
            num_copy >>= 1
        # 统计右边的连续0数量
        while num_copy != 0 and num_copy & 1 == 0:
            num_zeroes += 1
            num_copy >>= 1
        # 确定关键位位置并清除该位
        index = num_zeroes + num_ones
        num &= ~(1 << index)
        # 清除关键位右侧的所有位
        num &= ~((1 << index) - 1)
        # 从最低位开始设置1
        num |= (1 << num_ones + 1) - 1
        return num

单元测试

import unittest

class TestBits(unittest.TestCase):

    def test_get_next_largest(self):
        bits = Bits()
        self.assertRaises(Exception, bits.get_next_largest, None)
        self.assertRaises(Exception, bits.get_next_largest, 0)
        self.assertRaises(Exception, bits.get_next_largest, -1)
        num = int('011010111', base=2)
        expected = int('011011011', base=2)
        self.assertEqual(bits.get_next_largest(num), expected)
        print('Success: test_get_next_largest')

    def test_get_next_smallest(self):
        bits = Bits()
        self.assertRaises(Exception, bits.get_next_smallest, None)
        self.assertRaises(Exception, bits.get_next_smallest, 0)
        self.assertRaises(Exception, bits.get_next_smallest, -1)
        num = int('011010111', base=2)
        expected = int('011001111', base=2)
        self.assertEqual(bits.get_next_smallest(num), expected)
        print('Success: test_get_next_smallest')

def main():
    test = TestBits()
    test.test_get_next_largest()
    test.test_get_next_smallest()

if __name__ == '__main__':
    main()

实际应用

这种位操作技巧在实际开发中有多种应用场景:

  1. 内存管理:在需要分配特定大小的内存块时,快速找到最合适的块大小
  2. 哈希算法:优化哈希表的桶大小选择
  3. 图形处理:处理像素数据时快速调整位模式
  4. 压缩算法:在位级压缩数据时寻找最优表示

理解这些位操作技巧不仅能帮助我们解决特定问题,还能提升我们对计算机底层数据表示和处理的理解。

interactive-coding-challenges 120+ interactive Python coding interview challenges (algorithms and data structures). Includes Anki flashcards. interactive-coding-challenges 项目地址: https://gitcode.com/gh_mirrors/in/interactive-coding-challenges

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

滑芯桢

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

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

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

打赏作者

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

抵扣说明:

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

余额充值